Reputation: 165
Thanks for the suggestions. I beg your pardon for not being clear enough. Let me describe it again to the best of my ability.
There are two models - A & B. Model A has a subroutine (which is not a part of module) compns.f
which is called by a main program. Below, the compns.f
code:
compns.f: (Model A)
subroutine compns(deltim,fhout)
use var_repos, only: compns_var_dump
open(unit=nlunit,file=gfs_namelist) ! reads a file for the variables deltim and fhout
rewind (nlunit)
read(nlunit,nam_mrf)
print *, deltim,fhout ! deltim = 360.0, fhout = 6.0
CALL compns_var_dump(deltim,fhout) ! calls the subroutine and passes the variables
end
Another module which contains the subroutine compns_var_dump (to collect the variables) is
var_repos.f90
:
MODULE var_repos
IMPLICIT NONE
PUBLIC :: compns_var_dump
PUBLIC :: tstep_var_dump !!! to dump variables from another place
REAL, PUBLIC :: d_time ! dummy variable
! declare the variables which will go public here:
REAL, PUBLIC :: deltim, fhout
CONTAINS
SUBROUTINE compns_var_dump(deltim , fhout)
REAL, INTENT(inout) :: deltim , fhout
d_time = deltim
WRITE(*,*)'Inside var_repos: deltim = ',deltim,d_time
END SUBROUTINE compns_var_dump
SUBROUTINE tstep_var_dump
...
END SUBROUTINE tstep_var_dump
END MODULE var_repos
Now, I need the variables from var_repos.f90
in model B. The module in model B which requires them is the following:
mo_time_control.f90: (Model B)
MODULE time_control
PUBLIC :: get_delta_time
CONTAINS
REAL(dp) FUNCTION get_delta_time()
USE var_repos, ONLY: d_time
IMPLICIT NONE
REAL :: d_time
REAL :: a_time ! Testing
get_delta_time = d_time
a_time = d_time ! Testing
WRITE(*,*)'Inside function get_delta_time(): deltim= ',d_time,get_delta_time, a_time
END FUNCTION get_delta_time
END MODULE time_control
The outputs after running the models is as follows:
'Inside var_repos: deltim = ' 360.000 360.000
'Inside function get_delta_time(): deltim= ' 0.00000E+00 0.00000E+00 0.00000E+00
I hope that I am clear in this post. Is there a better way to do the above task? My philosophy was to collect the required variables from model A into one module through different subroutine calls, thus use this module as a repository and let model B use it for the variables it requires. Is this approach right?
Upvotes: 0
Views: 283
Reputation: 29391
Try this example:
MODULE var_repos
IMPLICIT NONE
PUBLIC :: compns_var_dump
REAL, PUBLIC :: deltim, var2
CONTAINS
SUBROUTINE compns_var_dump(deltim , fhout)
REAL, INTENT(in) :: deltim , fhout
WRITE(*,*)'Inside var_repos: args = ', deltim, fhout
var2 = fhout
END SUBROUTINE compns_var_dump
END MODULE var_repos
program test
use var_repos
call compns_var_dump ( 2.0, 3.0 )
write (*, *) "in main:", deltim, var2
end program test
The output is :
Inside var_repos: args = 2.00000000 3.00000000
in main: 0.00000000 3.00000000
I believe that answer is that the argument deltim of the subroutine and the module variable of the same name are different variables. Creating a subroutine dummy argument of the same name as the module variable masks the module module rather than automatically copying the value to the module variable. So in main the module variable deltim didn't receive the value 2 and is undefined. With the compiler I used the random value that it had was zero; the value might be different on a different compiler. On the other hand, the variables fhout and var2 are different, with the dummy argument fhout being actively copied to var2. Therefore the value of module var2 is set and available to any routine (here the main program) that uses the module.
Edit: The solution is what I show for argument fhout and module variable var2. Call the dummy arguments ARG_varX and the module variables GBL_varX. Inside the subroutine use assignment statements to copy each ARG_varX to GBL_varX. Then any procedures that uses the module will have access to the variables GBL_varX, which will have the values they were sent into the subroutine. Does this solve your problem.
Edit 2: Here is a version of your new code. It seems to work. If there is a bug either I fixed it or it is outside of the code that you are showing:
MODULE var_repos
IMPLICIT NONE
PUBLIC :: compns_var_dump
! declare the variables which will go public here:
REAL, PUBLIC :: GBL_deltim, GBL_fhout
CONTAINS
SUBROUTINE compns_var_dump(ARG_deltim, ARG_fhout)
REAL, INTENT(in) :: ARG_deltim , ARG_fhout
GBL_deltim = ARG_deltim
GBL_fhout = ARG_fhout
WRITE(*,*)'Inside compns_var_dump:', ARG_deltim, GBL_deltim, GBL_fhout
END SUBROUTINE compns_var_dump
END MODULE var_repos
! ------------------------------------------------------------
module my_b
contains
subroutine compns ()
use var_repos, only: compns_var_dump
real :: deltim, fhout
deltim = 360.0
fhout = 6.0
write (*, *) "compns:", deltim, fhout
CALL compns_var_dump(deltim,fhout) ! calls the subroutine and passes the variables
end subroutine compns
end module my_b
! ------------------------------------------------------------
MODULE time_control
PUBLIC :: get_delta_time
CONTAINS
FUNCTION get_delta_time()
USE var_repos, ONLY: GBL_deltim
IMPLICIT NONE
real :: get_delta_time
REAL :: a_time ! Testing
get_delta_time = GBL_deltim
a_time = GBL_deltim ! Testing
WRITE(*,*)'Inside function get_delta_time(): deltim= ', GBL_deltim, get_delta_time, a_time
END FUNCTION get_delta_time
END MODULE time_control
! ------------------------------------------------------------
program main
use var_repos, only: GBL_deltim, GBL_fhout
use my_b, only: compns
use time_control, only: get_delta_time
real :: local_var
call compns ()
local_var = get_delta_time ()
write (*, *) "main:", local_var, GBL_deltim, GBL_fhout
end program main
Upvotes: 1