I want to define inside a module some constants that are shared by several subroutines, but I get many error messages when I try to compile it (with the -c command):
Error: Unexpected assignment statement in MODULE
If I use the same code in a subroutine it works. Here's the code of the module:
module rkSetup
!High order embedded Runge-Kutta formulae, by P.J.Prince and J.R.Dormand,
!Journal of Computational and Applied Mathematics, vol. 7, 1981, pages 67-75
implicit none
INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(15)
integer, parameter :: s = 13 ! number of stages
integer, parameter :: p = 8 !< Order of the method
real(dp), dimension(s) :: a !< Runge-Kutta vector of nodes
real(dp), dimension(s) :: c !< Runge-Kutta vector of weigths
real(dp), dimension(s) :: d !< Runge-Kutta vector of weigths for high order
real(dp), dimension(s,s-1) :: b !< Runge-Kutta matrix
a = (/0.0_dp, 1.0_dp/18.0_dp, 1.0_dp/12.0_dp, 1.0_dp/8.0_dp, &
5.0_dp/16.0_dp,3.0_dp/8.0_dp,59.0_dp/400.0_dp,93.0_dp/200.0_dp, &
5490023248.0_dp/9719169821.0_dp, 13.0_dp/20.0_dp, &
1201146811.0_dp/1299019798.0_dp, 1.0_dp, 1.0_dp/)
c = 0.0_dp
d = 0.0_dp
d(1) = 14005451.0_dp/335480064.0_dp
d(6:) = (/-59238493.0_dp/1068277825.0_dp, &
181606767.0_dp/758867731.0_dp, &
561292985.0_dp/797845732.0_dp, &
-1041891430.0_dp/1371343529.0_dp, &
760417239.0_dp/1151165299.0_dp, &
118820643.0_dp/751138087.0_dp, &
-528747749.0_dp/2220607170.0_dp, 1.0_dp/4.0_dp/)
c(1) = 13451932.0_dp/455176623.0_dp
c(6:12) = (/-808719846.0_dp/976000145.0_dp, &
1757004468.0_dp/5645159321.0_dp, &
656045339.0_dp/265891186.0_dp, &
-3867574721.0_dp/1518517206.0_dp, &
465885868.0_dp/322736535.0_dp, &
53011238.0_dp/667516719.0_dp, 2.0_dp/45.0_dp/)
b = 0.0_dp
b(:,1) = (/0.0_dp, 1.0_dp/18.0_dp, 1.0_dp/48.0_dp, &
1.0_dp/32.0_dp, 5.0_dp/16.0_dp, 3.0_dp/80.0_dp, &
29443841.0_dp/614563906.0_dp, 16016141.0_dp/946692911.0_dp, &
39632708.0_dp/573591083.0_dp, 246121993.0_dp/1340847787.0_dp, &
-1028468189.0_dp/846180014.0_dp, 185892177.0_dp/718116043.0_dp, &
403863854.0_dp/491063109.0_dp/)
b(3,2) = 1.0_dp/16.0_dp
b(4:5,3) = (/3.0_dp/32.0_dp, -75.0_dp/64.0_dp /)
b(5:,4) = (/75.0_dp/64.0_dp,3.0_dp/16.0_dp, &
77736538.0_dp/692538347.0_dp, 61564180.0_dp/158732637.0_dp, &
-433636366.0_dp/683701615.0_dp, -37695042795.0_dp/15268766246.0_dp, &
8478235783.0_dp/508512852.0_dp, -3185094517.0_dp/667107341.0_dp, &
-5068492393.0_dp/434740067.0_dp/)
b(6:,5) = (/3.0_dp/20.0_dp, -28693883.0_dp/1125000000.0_dp, &
22789713.0_dp/633445777.0_dp, -421739975.0_dp/2616292301.0_dp, &
-309121744.0_dp/1061227803.0_dp, 1311729495.0_dp/1432422823.0_dp, &
-477755414.0_dp/1098053517.0_dp, -411421997.0_dp/543043805.0_dp/)
b(7:,6) = (/23124283.0_dp/1800000000.0_dp, &
545815736.0_dp/2771057229.0_dp,100302831.0_dp/723423059.0_dp, &
-12992083.0_dp/490766935.0_dp,-10304129995.0_dp/1701304382.0_dp, &
-703635378.0_dp/230739211.0_dp,652783627.0_dp/914296604.0_dp/)
b(8:,7) = (/-180193667.0_dp/1043307555.0_dp, &
790204164.0_dp/839813087.0_dp, 6005943493.0_dp/2108947869.0_dp, &
-48777925059.0_dp/3047939560.0_dp, 5731566787.0_dp/1027545527.0_dp, &
11173962825.0_dp/925320556.0_dp/)
b(9:,8) = (/800635310.0_dp/3783071287.0_dp, &
393006217.0_dp/1396673457.0_dp, 15336726248.0_dp/1032824649.0_dp, &
5232866602.0_dp/850066563.0_dp, -13158990841.0_dp/6184727034.0_dp /)
b(10:,9) = (/123872331.0_dp/1001029789.0_dp, &
-45442868181.0_dp/3398467696.0_dp,-4093664535.0_dp/808688257.0_dp, &
3936647629.0_dp/1978049680.0_dp/)
b(11:,10) = (/3065993473.0_dp/597172653.0_dp, &
3962137247.0_dp/1805957418.0_dp, -160528059.0_dp/685178525.0_dp/)
b(12:,11) = (/65686358.0_dp/487910083.0_dp, &
248638103.0_dp/1413531060.0_dp/)
end module rkSetup
How can I solve this?
As per Table 2.2 in the Fortran 2008 Standard, you may not place executable statements into a module directly.
If you want to initialize this data, either (a) do it during declaration, or (b) add a dedicated subroutine that you can call to do the initialization.
(a)
real(dp), dimension(s),parameter :: a = &
(/0.0_dp, 1.0_dp/18.0_dp, 1.0_dp/12.0_dp, 1.0_dp/8.0_dp, &
5.0_dp/16.0_dp,3.0_dp/8.0_dp,59.0_dp/400.0_dp,93.0_dp/200.0_dp, &
5490023248.0_dp/9719169821.0_dp, 13.0_dp/20.0_dp, &
1201146811.0_dp/1299019798.0_dp, 1.0_dp, 1.0_dp/)
(b)
module rkSetup
!High order embedded Runge-Kutta formulae, by P.J.Prince and J.R.Dormand,
!Journal of Computational and Applied Mathematics, vol. 7, 1981, pages 67-75
implicit none
INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(15)
!...
contains
subroutine init()
a = (/0.0_dp, 1.0_dp/18.0_dp, 1.0_dp/12.0_dp, 1.0_dp/8.0_dp, &
5.0_dp/16.0_dp,3.0_dp/8.0_dp,59.0_dp/400.0_dp,93.0_dp/200.0_dp, &
5490023248.0_dp/9719169821.0_dp, 13.0_dp/20.0_dp, &
1201146811.0_dp/1299019798.0_dp, 1.0_dp, 1.0_dp/)
!....
end subroutine
end module
Alexander Vogt is correct that you can define them in an initialization routine. However, if a,b,c,d
are constants, the most efficient thing to do is define them as parameters. Here is an example of two ways to do this:
module params
implicit none
integer, parameter :: s = 5
! -- Initialization method 1
real, parameter :: a(s) = (/ 1.2, 3.4, &
5.6, 7.8, 9.0 /)
! -- Initialization method 2
real :: b(s)
parameter( b = (/ 1.2, 3.4, &
5.6, 7.8, 9.0 /) )
end module params
program main
use params
write(*,'(a,5f6.2)') 'a is: ', a
write(*,'(a,5f6.2)') 'b is: ', b
end program main
If you wish to set a large parameter array with more than one dimension, consider using reshape
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With