Fortran subroutine parameter gets changed while calling [duplicate] - fortran

I want to know if it's possible to declare a variable and have declaration carry over to another subroutine or program (hence become global)
For example
program main
implicit none
call mysub
print *, x
end program main
subroutine mysub
implicit none
integer, parameter :: x = 1
end subroutine mysub
Would print "1"
Is this possible? I want to do this because a program I'm working on has large sets of variables that I would rather avoid copying unless necessary.

The most straightforward way to do this in modern Fortran is with modules.
Consider
module globals
implicit none
integer :: x
end module globals
program main
use globals
implicit none
call mysub
print *,x
end program main
subroutine mysub
use globals
implicit none
x = 1
end subroutine mysub
In this paradigm you specify your "global" variables within the module and use that module everywhere you want access to them.
If you are just using this to declare contants (parameters) you can simplify this to:
module globals
implicit none
integer, parameter :: x=1
end module globals
program main
use globals
implicit none
print *,x
end program main
The older method to accomplish this involved common blocks and includeing files that declared them every procedure that accessed them. If you find a tutorial dealing with the common block method I advise you to ignore them and avoid their use in new code.

Related

Difference between subroutine inside module "contains" and outside module

I have a large source code where subroutines in modules are defined outside the module ... end module statement (ie. not inside a contains statement). I've included a simplified module below:
module core
implicit none
type :: disc_status
sequence
real*8 :: alpha1, alpha2, alpha3
end type disc_status
end module core
subroutine tester(input)
use core
type(disc_status), intent(in) :: input
print *, input%alpha1, input%alpha2, input%alpha3
end subroutine tester
Here's an example program using the module and subroutine:
program flyingDiscSimulator
use core
implicit none
type(disc_status) :: disc
disc%alpha1 = 1.1D0
disc%alpha2 = 1.2D0
disc%alpha3 = 1.3D0
call tester(disc)
print *, 'it works'
end program flyingDiscSimulator
Normally, I end up seeing subroutines use the contains statement within a module:
module core
implicit none
type :: disc_status
sequence
real*8 :: alpha1, alpha2, alpha3
end type disc_status
contains
subroutine tester(input)
type(disc_status), intent(in) :: input
print *, input%alpha1, input%alpha2, input%alpha3
end subroutine tester
end module core
However, the program file referenced above doesn't require any changes to use either way of including a subroutine in a module (using gfortran anyways). Thus, there appears to be no difference in the usage of the module or it's subroutine between the two solutions. Are there any "under the hood" differences between the two styles?
The versions
module m
contains
subroutine s()
end subroutine s
end module m
and
module m
end module m
subroutine s()
end subroutine s
say completely different things, but in the case of the question the end results are much the same.
The first version here creates a module procedure s with host m; the second version has an external procedure s with no host.
Although the example of the question has the external procedure using the module, there is more generally a difference: the module procedure has access to all entities in the module (except when made inaccessible through an import statement or by being obscured by local names; the external procedure using the module has access only to those public entities.
However, come the main program the effects are different. The external subroutine and its name are global entities. Going to my second version, then
program main
call s
end program
is a valid program which calls the external subroutine s. This subroutine reference is valid because the implicit interface for s in the main program suffices. If the external subroutine s were such than an explicit interface were required then main program here would not be allowed. It is acceptable, but not required, to have an external s statement in the main program to reinforce to the reader that the subroutine is an external one (with implicit interface). (implicit none external would make external s necessary.)
The example of the question is such that an explicit interface is not required.
A module procedure always has an explicit interface available when accessible. However, a module procedure is not a global entity and its name is not a global identifier.
Under the hood, there are implementation differences (stemming from the above): most notably compilers will often "name mangle" module procedures.
In summary, there are differences between the two approaches of the question, but they won't be noticed by the programmer in this case.
The procedure inside the module will have an explicit interface (aka the compiler knows about the arguments' characteristics).
Whereas the procedure outside of the module will have an implicit interface (aka the compiler must make assumptions about the arguments).
Explicit interfaces help the compiler to find programming errors and are therefore favourable.
For a more indepth discussion of advantages see for example this answer.
I am not even sure if it is valid Fortran to call tester inside the program when it is defined outside of core?
The line use core should just make the module's public objects known and the tester procedure needs its own external tester line.

passing allocated array from subroutine to the main program in fortran; use or module? interface?

I want to allocate an array in a subroutine, and then use this array in the main program and pass it to some other subroutine. In the past (F77?) the passing could be done in a common block, but nowadays the favored procedure seems to be to use a module. When I try this, as in the code example, the compiler tells me
Rank mismatch in argument ‘f’ at (1) (scalar and rank-1)
Apparently, the main program thinks that 'f' is a scalar: but, I read this code to mean that I've declared it as a one-dimensional array, both inside the subroutine and in the main program. What am I missing?
I've tried variations, such as declaring the variables as part of the module, but nothing I could think of made the compilation error-free (and some produced many more errors ;-( ). Any insight is most appreciated.
module subs
contains
subroutine makef(f)
end subroutine makef
end module subs
c-----------------------------------------------------------------------
program work
use subs
implicit none
real, allocatable :: f(:)
call makef(f)
write (*,*) f
stop
end
c---------------------------------------------------------------------
subroutine makef(f)
implicit none
real, allocatable, intent(out) :: f(:)
integer :: i
integer :: is
is=10
allocate(f(-is:is))
do i=-is,is
f(i)=i
end do
return
end subroutine makef
Modules in Fortran are not like header files in other languages which merely provide information about things defined elsewhere. There is the concept of "deferred definition" (submodules) but in this case the module should say everything about the subroutine, not simply attempt to point to its existence.
In the example of the question, we have: the main program; a module subs with module procedure makef; an external subroutine makef.
The main program uses the module subs, and its procedure makef, so reference in the main program to makef is to that module procedure not the external subroutine makef.
The module subroutine makef has the argument f which has no declaration statements, making it an implicitly declared scalar/external function. This is the compiler's message. Use implicit none in modules, just as it's in the main program and external subroutine here.
The entire definition of the subroutine should be placed in the module:
module subs
implicit none
contains
subroutine makef(f)
real, allocatable, intent(out) :: f(:)
integer :: i
integer :: is
is=10
allocate(f(-is:is))
do i=-is,is
f(i)=i
end do
end subroutine makef
end module subs
Alternatively, if one does want to refer to the later implementation of an external procedure an interface block can feature in the module without declaring the subroutine itself. In this case it will still be necessary to specify the complete interface:
module subs
implicit none
! An interface block to give an explicit interface to the external subroutine makef
interface
subroutine makef(f)
implicit none
real, allocatable, intent(out) :: f(:)
end subroutine makef
end interface
end module subs
In this case, don't prefer the interface block.
You only placed the copy of the first and the last line into the module. That can't work. You must move the whole subroutine into the module.

How to declare a global variable to be accessible in the main program and external function? [duplicate]

I want to know if it's possible to declare a variable and have declaration carry over to another subroutine or program (hence become global)
For example
program main
implicit none
call mysub
print *, x
end program main
subroutine mysub
implicit none
integer, parameter :: x = 1
end subroutine mysub
Would print "1"
Is this possible? I want to do this because a program I'm working on has large sets of variables that I would rather avoid copying unless necessary.
The most straightforward way to do this in modern Fortran is with modules.
Consider
module globals
implicit none
integer :: x
end module globals
program main
use globals
implicit none
call mysub
print *,x
end program main
subroutine mysub
use globals
implicit none
x = 1
end subroutine mysub
In this paradigm you specify your "global" variables within the module and use that module everywhere you want access to them.
If you are just using this to declare contants (parameters) you can simplify this to:
module globals
implicit none
integer, parameter :: x=1
end module globals
program main
use globals
implicit none
print *,x
end program main
The older method to accomplish this involved common blocks and includeing files that declared them every procedure that accessed them. If you find a tutorial dealing with the common block method I advise you to ignore them and avoid their use in new code.

Nested contains statement

I have a program like this
program
call one()
contains one()
some vars
contains two()
use the vars of one
define its own vars
contains three()
use the vars of both one and two
This doesn't compile because Fortran allows only the first contains statement.
I used this design to avoid passing and retyping all the variables of one() into two() and three().
How can I rewrite the program so that the variable sharing is achieved?
I cannot define all the variable before the statement call one().
The code will be to hard to manage, I need the feature :
parent subroutine cannot access internal subroutine variables.
Maybe a solution is to use pointer
call one(pointer_to_two)
then define the routine two() in its own module.
But I find this design complicate with my limited Fortran skills.
And I'm worried it will impact performance.
Should I use a common block?
I use the latest dialect of Fortran with the Intel compiler.
Below is 'compilable' example.
program nested_routines
call one()
contains
subroutine one()
integer :: var_from_one = 10
print *, 1
call b()
contains
subroutine two()
integer :: var_from_two = 20
print *, 2, var_from_one
call c()
contains
subroutine three()
print *, 3, var_from_one, var_from_two
end subroutine
end subroutine
end subroutine
end module
I recommend placing your procedures (subroutines and functions) into a module after a single "contains" and using that module from your main program. The local variables of each procedure will be hidden their callers. The way that this differs from your goals is that you have to redeclare variables. I dislike the inheritance of all variables in a subroutine contained in another because it is possible to mistakenly reuse a variable. If you have a few variables that are shared across many procedures, perhaps the appropriate design choice is to make them global. With Fortran >=90, a module variable is better method for a global variable than common blocks. If you have variables that are communicated between a limited number of procedures, it is generally better to use arguments because that makes the information flow clearer.
this might be possible if there is a separate module for each of the functions specific variables and a separate module for each function implementation
watch out for the order of the module compilation, according to the usage hierarchy necessity
also, i have no idea on the performance effect of doing this
module m1_var
implicit none
contains
end module m1_var
!========================================================================================================================
module m2_var
implicit none
contains
end module m2_var
!========================================================================================================================
module m3_var
implicit none
contains
end module m3_var
!========================================================================================================================
module m3_sub
implicit none
contains
subroutine s3()
use m2_var !to see varibles
!arguments
!local
!allocation
!implementation
end subroutine s3
end module m3_sub
!========================================================================================================================
module m2_sub
implicit none
contains
subroutine s2()
use m3_sub
use m1_var
!arguments
!local
!allocation
!implementation
call s3
end subroutine s2
end module m2_sub
!========================================================================================================================
module m1_sub
use m1_var
implicit none
contains
subroutine s1()
use m2_sub
!arguments
!local
!allocation
!implementation
! call s2
end subroutine s1
end module m1_sub
!========================================================================================================================
program nestmoduse
use m1_sub
implicit none
call s1
end program nestmoduse

How to print data from a module used in my fortran subroutine

Thanks for the help in advance..
Kindly I want to print data in an output file of the main FORTRAN program and these data defined in a module and I already declare using that module in the main program. but I couldn't get the write statements neither in the main program nor in the module.
MODULE model
IMPLICIT NONE
SUBROUTINE model_initialize
IMPLICIT NONE
INTEGER a,dim REAL(float) :: E,nu
REAL(float) :: lambda,mu
E=5000 lambda = E*nu/(1.d0+nu)/(1.d0-2.d0*nu)
mu = E/2.d0/(1.d0+nu)
RETURN
END SUBROUTINE model_initialize
Write (6,)'Lambda',lambda
Write (6,)'mu',mu
END MODULE model
SUBROUTINE XXXX
USE model
IMPLICIT NONE
CALL model_initialize
Write (6,)'Lambda',lambda
Write (6,)'mu',mu
END SUBROUTINE XXX
When I put the write statements in the module or in the main subroutine , I cant see them in the output.
Many thanks for the help
Msekh
Mgilson has already provided you with an example that should work, but the code you posted will not compile. This is why:
Your subroutine model_initialize is in the "specification part" of your module. It should either be external (like xxxx) or internal to the module (in which case you have to provide a contains statement).
The variables in model_initialize are local to the subroutine and will not be accessible outside it.
You cannot have executable code (like write) in the specification part of a module, only in internal procedures.
float is not a native Fortran kind, you have to use the numerical parameters (usually 4, 8, 16), define your own, or use the definitions in the iso_fortran_env module.
That said, if you only need to define some data you want to make accessible, you can simply put that directly in the module like this:
module model
use iso_fortran_env
implicit none
integer :: A, dim
real(real32) :: E, nu, lambda, mu
E = 5000
lambda = E*nu/(1.d0+nu)/(1.d0-2.d0*nu) ! <-- nu is undefined
mu = E/2.d0/(1.d0+nu)
contains
subroutine xxxx
write (6,*) 'lambda', lambda
write (6,*) 'mu', mu
end subroutine xxxx
end module model
do you mean something like:
module material
real :: stress = 6.0
save
end module material
subroutine xxx()
use material, only: stress
write(6,*) stress
end subroutine
program main
call xxx()
end program main
This will write the value of stress to the file-like object connected with unit 6 (usually this is stdout, but it might create a new file called fort.6 depending on compiler and environment settings).