ChemEng stuff followers

The 4th-order Runge-Kutta method for systems of ode in F90

 Here is a presentation of the algorithm and code for the solutions of systems of linear ordinary differential equations by means of the 4th-order Runge-Kutta method, along with some comments.

Contents

    Two reference texts

    Much of the background can be found, partially, in well known textbooks. However, neither the code nor the algorithm is usually presented.

    Actually, the book of Numerical Methods for Engineers by Chapra, SC and Canale, RP presents an algorithm for this case but have been slightly modified to our purpose. As you may know, an algorith is a general procedure to implement a numerical method so that it can be implemented in any language (that is the problem).

    The book of Differential Equations by Zill, DG is also a good source for examples concerning the numerical solution of systems of ode. In other wordsm, you may choose some exercises from Zill's book and test your program.

    These two books are recommended for the reader if a wider view is required. There are several other options to improve the 4th-order Runge-Kutta method but I think this a good point of start.

    The method formulae

    For short, the 4th-order Runge-Kutta method is better presented if a general set of two ode's is used. If more ode are at hand, the formulae can be easily extended.

    Then, consider the system of linear ode's,

    $\dfrac{dy_1}{dx}=f(x,y_1,y_2)$        Eq. (01)

    $\dfrac{dy_2}{dx}=g(x,y_1,y_2)$        Eq. (02)

    where $f$ and $g$ are two linear functions on $y_1$ and $y_2$. The form of $f$ and $g$ on x is not relevant. Equations (01-02) are subjected to the following conditions,

    $y_1(x=x_0)=y_{1i}$        Eq. (03)

    $y_2(x=x_0)=y_{2i}$        Eq. (04)

    Using the 4th-order Runge-Kutta method, the system of Eqs. (01-02) is found to have the solution,

    $y_{1,i+1}=y_{1,i} + \dfrac{1}{6}\left[ k_{1,1}+2\left( k_{1,2}+k_{1,3} \right) + k_{1,4} \right]$

    $y_{2,i+1}=y_{2,i} + \dfrac{1}{6}\left[ k_{2,1}+2\left( k_{2,2}+k_{2,3} \right) + k_{2,4} \right]$        Eq. (05)

    where the parameters $k_{1,1}$ through $k_{2,4}$ are calculated from,

    $k_{1,1}=f(x_i,y_{1,i},y_{2,i})$

    $k_{2,1}=g(x_i,y_{1,i},y_{2,i})$

    $k_{1,2}=f\left(x_i+\dfrac{1}{2}h,y_{1,i}+\dfrac{1}{2}k_{1,1},y_{2,i}+\dfrac{1}{2}k_{2,1}\right)$

    $k_{2,2}=g\left(x_i+\dfrac{1}{2}h,y_{1,i}+\dfrac{1}{2}k_{1,1},y_{2,i}+\dfrac{1}{2}k_{2,1}\right)$

    $k_{1,3}=f\left(x_i+\dfrac{1}{2}h,y_{1,i}+\dfrac{1}{2}k_{1,2},y_{2,i}+\dfrac{1}{2}k_{2,2}\right)$

    $k_{2,3}=g\left(x_i+\dfrac{1}{2}h,y_{1,i}+\dfrac{1}{2}k_{1,2},y_{2,i}+\dfrac{1}{2}k_{2,2}\right)$

    $k_{1,4}=f(x_i+h,y_{1,i}+k_{1,3}h,y_{2,i}+k_{2,3}h)$

    $k_{2,4}=g(x_i+h,y_{1,i}+k_{1,3}h,y_{2,i}+k_{2,3}h)$        Eq. (06)

    As you can see, Eqs. (05-06) are an extension of the formulae for the implementation of the method on a single ode.

    The algorithm for the 4th-order Runge-Kutta method applied to a system of linear ode's

    As mentioned before, this algorithm is based on that presented in the book of Chapra and Canale. This is as follows

    Main program

    Program

    Assign known data as parameters

    n = number of ode's

    m = number of desired iterations

    yi = initial values for the n dependent variables

    xi = initial value of the independent variable

    xf = desired final value of computation for the independent varaible

    dx = (xf - xi)/m <- Step size calculation


    Load variables


    x = xi <- Initial value of x

    Do for i = 1,n

        y(i) = yi(i)

    End do


    Loop for iterations

    Do for i = 1,m

        xend = x + dx

        If (xend > xf) Then

        xend = xf 

        End if

        h = dx

        Call INTEGRATOR(x,y,n,h,xend)

        Print results for every iteration

        If (x >= xf) Exit

    End do

    End program

    Subroutine for advancing a step

    Subroutine INTEGRATOR(x,y,n,h,xend)

    Do

        If (xend - x < h) Then

        h = xend - x

        End if

        Call RK4(x,y,n,h)

        If (x >= xend) Exit

    End do

    Return

    End subroutine

    Subroutine for 4th-order Runge-Kutta applied to a system of ode's

    Subroutine RK4(x,y,n,h)

    Call DERIVS(x,y,k1)

        Do for i = 1,n

        ym(i) = y(i) + k1(i)*h/2

        End do


    Call DERIVS(x + h/2,ym,k2)

        Do for i = 1,n

        ym(i) = y(i) + k2(i)*h/2

        End do


    Call DERIVS(x + h/2,ym,k3)

        Do for i = 1,n

        ye(i) = y(i) + k3(i)*h

        End do


    Call DERIVS(x + h,ye,k4)

        Do for i = 1,n

        Slope(i) = (k1(i) + 2*(k2(i) + k3(i)) + k4(i))/6

        y(i) = y(i) + Slope(i)*h

        End do

    x = x + h

    Return

    End subroutine

    Subroutine to include the system of ode's

    Subroutine DERIVS(x,y,k)

    dydx(1) = ...

    dydx(2) = ...

    k1(1) = ...

    k1(2) = ...

    etc.

    end subroutine

    The code for the 4th-order Runge-Kutta method for systems of oden in F90

    At this stage, going from the algorithm should be easy but sometimes it can be challenging. Also, every programmer may arrive to his/her own implementation so that different accuracies, efficiencies and code length can be found.

    The implementation presented here is based, as much as possible, on the algorithm already presented. For this, three different f90 files, using modules, were created:

    • one for the main program (main.f90)
    • another one for the subroutines (MySubroutines.f90)
    • and another one for the data types (nrtypes.f90).

    How does the program works?

    Well, it is not difficult to observe from the algorithm that the main program calls all subroutines via Integrator. Therefore, it is reasonable to plan having all subroutines in a single file: MySubroutines.f90.

    Also, depending on what kind of compiler you are using the series of commands to compile and execute the program may differ. In my case, I am using a commercial compiler so that the whole thing is very easy.

    The code

    You may follow the links below to download the source code files mentioned previously,

    The set of ode's solved by this program is the same presented by Chapra and Canale in their book,

    $\dfrac{dy_1}{dx}=-0.5y_1$
    $\dfrac{dy_2}{dx}=4-0.3y_2-0.1y_1$

    (which you will find in the DERIVS subroutine already) subject to the conditions,

    $y_1(x=0)=4$ 
    and 
    $y_2(x=0)=6$

    which you will find in the main.f90 file. The solution of the equations is performed with a step size $h=0.5$ and is presented from $x=0$ to $x=4$.

    These program will output the result which is the same presented too in the book of Chapra and Canale.

    Fig. f90 results and those presented by Chapra and Canale in their book for comparison.

    If you just the files and managed to compile it and make it run you will for sure get the black window with the results as shown below. However, you should test this program against other cases and see how it goes.

    I just did and some improvements and comments can be made to the algorithm and the code. These are presented in the following section.

    Some improvements to the algorithm

    Well, writting the code for the 4th-order Runge-Kutta method according to the algorithm of Chapra and Canale was quite straight. However, when trying to solve another system it simply did not work. Here are some comments on this test:

    • First, the new system I try to solve have a wider range of integration from $x=-5$ to $x=5$. What I found was that as the program was taking steps it went into the negative values rather than to $x=5$. In order to fix this problem I had to perform some manual calculations to follow the loginc of the program which i did not want.
    • What I found was that xout was useless and that it was the cause of the problem. What I did was to erase xout and replace it in the main program loop dor iterations  by dx (which is the step size). It works!
    As a side improvement is that you should ask the program for certain accuracy rather than doing it manually by changing the number of steps in the range. You should of course introduce other parameters and conditionals but it could save you time.

    Another situation that I found was that of higher order ODE. Any ODE of order higher than 1 can be split into a set of first order ODE by means of a change of variables. This however leads to some possible difficulties: not enough or unknown boundary conditions for all these new variables. I shall discuss this topic later in another post.

    This is the end of the post. I hope you may find it useful and easy to adapt for your own benefit....

    Any question? Write in the comments and I shall try to help.

    Perhaps the following post may be of interest for you

    =========
    Ildebrando

    No comments:

    Post a Comment

    Most popular posts