Today I'm trying to evaluate this differential equation for internal energy in a gas in Fortran 90:
du / dt = dT / dt = - λ / ρ
Where u is the internal energy and λ is the cooling function (and they are both functions of temperature T only). ρ is the mass density and we can assume it's constant.
I'm using a Runge-Kutta 2nd order method (heun), and I'm sure I wrote the actual solving algorithm correctly, but I'm pretty sure I'm messing up the implementation. I'm also not sure how to efficiently choose an arbitrary energy scale.
I'm implementing the Right Hand Side with this subroutine:
MODULE RHS
! right hand side
IMPLICIT NONE
CONTAINS
SUBROUTINE dydx(neq, y, f)
INTEGER, INTENT(IN) :: neq
REAL*8, DIMENSION(neq), INTENT(IN) :: y
REAL*8, DIMENSION(neq), INTENT(OUT) :: f
f(1) = -y(1)
END SUBROUTINE dydx
END MODULE RHS
And this is the Heun algorithm I'm using:
SUBROUTINE heun(neq, h, yold, ynew)
INTEGER, INTENT(IN) :: neq
REAL*8, INTENT(IN) :: h
REAL*8, DIMENSION(neq), INTENT(IN) ::yold
REAL*8, DIMENSION(neq), INTENT(OUT) :: ynew
REAL*8, DIMENSION(neq) :: f, ftilde
INTEGER :: i
CALL dydx(neq, yold, f)
DO i=1, neq
ynew(i) = yold(i) + h*f(i)
END DO
CALL dydx(neq, ynew, ftilde)
DO i=1, neq
ynew(i) = yold(i) + 0.5d0*h*(f(i) + ftilde(i))
END DO
END SUBROUTINE heun
Considering both lambda and rho are n-dimensional arrays, i'm saving the results in an array called u_tilde, selecting a starting condition at T = 1,000,000 K
h = 1.d0/n
u_tilde(1) = lambda(n)/density(n) ! lambda(3) is at about T=one million
DO i = 2, n
CALL heun(1, h*i, u_tilde(i-1), u_tilde(i))
ENDDO
This gives me this weird plot for temperature over time.
I would like to have a starting temperature of one million kelvin, and then have it cool down to 10.000 K and see how long it takes. How do I implement these boundary conditions? What am I doing wrong in RHS and in setting up the calculation loop in the program?

Your implementation of
dydxonly assigns the first element.Also, there is no need to define loops for each step, as Fortran90 can do vector operations.
For a modular design, I suggest implementing a custom type that holds your model data, like the mass density and the cooling coefficient.
Here is an example simple implementation, that only holds one scalar value, such that y' = -c y
and the above module is used for some cooling simulations with
Note that I am only tracking the 1st element of
neqcomponents of y.The sample output shows exponential decay starting from 1000
Also, if you wanted the above to implement runge-kutta 4th order you can include the following in the
mod_diffeqmodule