给出一个以状态空间形式表示的微分方程的线性系统,
dy = A*y + b
在Matlab中,我可以定义函数
function [dy] = fun(t,y,A,b)
dy = A*y+b;
end
如果我想进行时间积分,可以在主程序中编写:
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);
前提是我之前已经定义了M
,C
和K
矩阵以及力矢量F
,时间跨度tspan
和初始条件{{ 1}}。
现在我要在Fortran中使用它。为此,我找到了一个ode求解器online。这是Shampine和Gordon ODE求解器(可能与MATLAB中使用的求解器相同),它集成了形式为的微分方程
y0
就像MATLAB! 如果我定义了一个子程序,例如(the online example)
y' = f(t,y)
我可以整合这个方程组。
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
这工作正常,我可以在主程序上测试ode求解器:
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
这是问题所在。现在,我想对状态空间形式的方程式进行时间积分。问题:如何将变量program main
call test01()
end program main
和A
传递给fun函数以进行集成?
b
我无法更改函数定义中的参数数量,因为ode积分器只需要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
即可。
Fortran中是否有类似MATLAB的东西,我可以在其中定义函数fun(t,y,yp)
和第二个函数fun(t,y,yp,A,b)
并集成第二个函数?
还是告诉Fortran A和b是某种全局变量? (我虽然使用了通用块,但它不接受可分配地址)