I wanted to make it easier to change a certain function which will be used by a subroutine in a fortran project. However I can not get it to work. I have seen quite a few examples which use the external
, however I am not sure if I have to use it, since I put all my function and subroutines in modules.
Here is a simplified example of the problem I am dealing with:
I have the program in a separate file:
program test
use Parameters
use circArrayConstructer
use velocity
use RungeKutta4
implicit none
integer(is) :: N, P, nsteps, i, j
real(fd) :: D, dt
real(fd), allocatable :: coor(:,:)
integer(is), allocatable :: topo(:,:)
integer(is) :: error
read (*,*) D, nsteps, N, P
dt = 1.0 / nsteps
call circArray ( 0.5_fd, 0.5_fd, 0.2_fd, 0.2_fd, N, coor, topo, error )
do i = 1, P
do j = 1, nsteps
if ( mod(P,2) > 0 ) then
call RK4 ( dt, coor, D, vel1, coor )
else
call RK4 ( dt, coor, D, vel2, coor )
end if
end do
end do
end program test
I put each subroutine and all the functions in a separate module and each module has its own file:
The module Parameters
just defines constants and variable types:
module Parameters
implicit none
integer, parameter :: fs = selected_real_kind(6)
integer, parameter :: fd = selected_real_kind(15)
integer, parameter :: is = selected_int_kind(9)
integer, parameter :: id = selected_int_kind(18)
real(fd), parameter :: PI = 3.141592653589793
end module Parameters
Module circArrayConstructer
contains the subroutine circArray
which has the output error
, coor
and topo
, the last two have dimensions N
by 2 and since N
in an input they have to be allocated.
Module RungeKutta4
contains the subroutine RK4
which is an implementation of the 4th order Runge Kutta method:
module RungeKutta4
use Parameters
use velocity
implicit none
contains
subroutine RK4 ( dt, coorOld, D, vel, coorNew )
implicit none
real(fd), intent(in ) :: dt
real(fd), intent(in ) :: D
real(fd), intent(in ) :: coorOld(:,:)
real(fd), intent(out) :: coorNew(:,:)
real(fd), dimension(size(coorOld,1), size(coorOld,2)) :: k1, k2, k3, k4
real(fd), external :: vel
k1 = vel ( coorOld , D )
k2 = vel ( coorOld + 0.5 * dt * k1, D )
k3 = vel ( coorOld + 0.5 * dt * k2, D )
k4 = vel ( coorOld + dt * k3, D )
coorNew = coorOld + dt / 6.0 * (k1 + 2 * (k2 + k3) + k4)
end subroutine RK4
end module RungeKutta4
And module velocity
contains multiple functions:
module velocity
use Parameters
implicit none
contains
function vel1 ( coor, D )
implicit none
real(fd), intent(in) :: D
real(fd), intent(in) :: coor(:,:)
real(fd), dimension(size(coor,1), size(coor,2)) :: vel1
vel1(:,1) = -2.0 * D * coor(:,2) * sin(PI * coor(:,1)) * cos(PI * coor(:,2) ** 2)
vel1(:,2) = D * cos(PI * coor(:,1)) * sin(PI * coor(:,2) ** 2)
end function vel1
function vel2 ( coor, D )
implicit none
real(fd), intent(in) :: D
real(fd), intent(in) :: coor(:,:)
real(fd), dimension(size(coor,1), size(coor,2)) :: vel2
vel2(:,1) = 2.0 * D * (1 - coor(:,2)) * sin(PI * coor(:,1)) * cos(PI * (1 - coor(:,2)) ** 2)
vel2(:,2) = D * cos(PI * coor(:,1)) * sin(PI * (1 - coor(:,2)) ** 2)
end function vel2
end module velocity
Currently when I try to compile the program I get the error: Interface mismatch in dummy procedure 'vel': Type/rank mismatch in function result.
I have tried all kinds of things, such as changing the declaration of vel
in RungeKutta4
to real(fd), external :: vel(:,:)
but that gives conflicting attributes. But I have run out of ideas on how to make the code work.