1

Given a linear system of differential equations, represented in state space form,

dy = A*y + b

In Matlab, I can define the function

function [dy] = fun(t,y,A,b)
    dy = A*y+b;
end

And if I want to do a time integration, I can write in the main program:

n = size(M,1);
A = [zeros(n,n) eye(n,n) ; -M\K -M\C];
b = [zeros(n,1) M\F];
odefun = @(t,y) fun(t,y,A,b)

[TOUT,YOUT] = ode15s(odefun,tspan,y0);

provided I have previously defined the M, C and K matrices and the force vector F, the time span tspan and initial conditions y0.


Now I want this in Fortran. To do that, I found an ode solver online. This is Shampine and Gordon ODE solver (presumably the same solver utilized in MATLAB), which integrates differential equations of the form

y' = f(t,y)

Exactly like MATLAB! If I define a subroutine like (the online example)

subroutine fun( t, y, yp )
    implicit none
    double precision :: t
    double precision :: y(2)
    double precision :: yp(2)

    yp(1) = y(2)
    yp(2) = -y(1)

    return
end subroutine fun

I can integrate this system of equations.

subroutine test01()
    implicit none

    integer :: neqn = 2
    double precision :: abserr
    external fun
    integer :: i
    integer :: iflag
    integer :: iwork(5)
    double precision :: pi = 3.141592653589793D+00
    double precision :: relerr
    integer, parameter :: step_num = 12
    double precision :: t
    double precision :: tout
    double precision :: work(100+21*neqn)
    double precision :: y(neqn)

    abserr = 0.00001D+00
    relerr = 0.00001D+00

    iflag = 1

    t = 0.0D+00
    y(1) = 1.0D+00
    y(2) = 0.0D+00

    write ( *, '(2x,f8.4,2x,2g14.6)' ) t, y(1:neqn)

    do i = 1, step_num

    tout = dble(i)*2.0d0 * pi / dble(step_num)
    call ode ( f01, neqn, y, t, tout, relerr, abserr, iflag, work, iwork )

    if ( iflag /= 2 ) then
      write ( *, '(a)' ) 'TEST01 - Fatal error!'
      write ( *, '(a,i8)' ) '  ODE returned IFLAG = ', iflag
      exit
    end if

    write ( *, '(2x,f8.4,2x,2g14.6)' ) t, y(1:neqn)

    end do

    return
end subroutine test01

This works fine and I can test the ode solver on the main program:

program main
    call test01()
end program main

Here is the problem. Now I want to do a time integration of the equations in state space form. The problem: how to pass the variables A and b to the function fun to be integrated?

subroutine fun( t, y, yp )
    implicit none
    double precision :: t
    double precision :: y(:)
    double precision :: yp(:)

    yp = matmul(A,y) + b

    return
end subroutine fun

I cannot change the number of arguments in the function definition, because the ode integrator requires a fun(t,y,yp) and nothing else.

Is there something in Fortran like MATLAB, where I can define a function fun(t,y,yp,A,b) and a second function fun2 = @(t,x) fun(t,y,yp,A,b) and integrate the second function?

Or tell Fortran A and b are sort of global variables? (I though using the common blocks, but it does not accept allocatables)

Thales
  • 1,181
  • 9
  • 10

0 Answers0