Fortran: Whole array operations in Fixed Form Source - module

I am getting "Segmentation Fault" error over and over again, while using my subroutines (I have put all of them in MODULEs) with a code written in Fixed Form Source (during fortran77 days).
The original make file (Linux platform) is a mess, it compiles only ".f" source, so I had to change the extensions of my files from ".f90" to ".f", and have left first 7 columns blank in my modules.
My modules extensively use whole array operations and operations on array-sections, and I declare the variables in F90 style, many of them are assumed-size arrays.
My question:- although the compiler compiles these modules (having whole-array/array-section operations) without any warning/error, however is this "segmentation fault" due to the usage of modules with whole-array/array-section operations (kept in .f files) in a legacy code?
For example I have written following code in "algebra.f" module:
function dyad_vv(v1,v2) !dyadic product of two vectors
real*8, dimension(:)::v1,v2
real*8, dimension(size(v1,1),size(v2,1))::dyad_vv
integer i,j
do i=1,size(v1,1)
do j=1,size(v2,1)
dyad_vv(i,j)=v1(i)*v2(j)
end do
end do
end function
!==================================
function dot_mv(m,v) !dot product of a matrix and a vector
real*8, dimension(:,:)::m
real*8, dimension(:)::v
real*8, dimension(size(m,1))::dot_mv
integer i,j
do i=1,size(m,1)
dot_mv(i)=0.0000D0
do j=1,size(v,1)
dot_mv(i)=dot_mv(i)+m(i,j)*v(j)
end do
end do
end function
!==================================
function dot_vm(v,m) !dot product of a vector and a matrix
real*8, dimension(:)::v
real*8, dimension(:,:)::m
real*8, dimension(size(m,2))::dot_vm
integer i,j
do i=1,size(m,2)
dot_vm(i)=0.0000D0
do j=1,size(v,1)
dot_vm(i)=dot_vm(i)+v(j)*m(j,i)
end do
end do
end function

To expand a little on my already over-long comment:
Segmentation faults in Fortran programs generally arise from either (a) attempting to access an array element outside the array bounds, or (b) mismatching procedure actual arguments and dummy arguments.
Fortunately, intelligent use of your compiler can help you spot both these situations. For (a) you need to switch on run-time array bounds checking, and for (b) you need to switch on compile-time subroutine interface checking. Your compiler manual will tell you what flags you need to set.
One of the advantages of modern Fortran, in particular of modules is that you get procedure interface checking for free as it were, the compiler takes care, at compile time, of checking that dummy and actual arguments match.
So I don't think your problem stems directly from writing modern Fortran in fixed-source form. But I do think that writing modern Fortran in fixed-source form to avoid re-writing your makefile and to avoid upgrading some FORTRAN77 is a sufficiently perverse activity that you will find it painful in the short run, and regret it in the long run as you continue to develop degraded code.
Face up to it, refactor now.

Related

Explicit interface in Fortran [duplicate]

I'm very new to Fortran, and for my research I need to get a monster of a model running, so I am learning as I am going along. So I'm sorry if I ask a "stupid" question.
I'm trying to compile (Mac OSX, from the command line) and I've already managed to solve a few things, but now I've come across something I am not sure how to fix. I think I get the idea behind the error, but again, not sure how to fix.
The model is huge, so I will only post the code sections that I think are relevant (though I could be wrong). I have a file with several subroutines, that starts with:
!==========================================================================================!
! This subroutine simply updates the budget variables. !
!------------------------------------------------------------------------------------------!
subroutine update_budget(csite,lsl,ipaa,ipaz)
use ed_state_vars, only : sitetype ! ! structure
implicit none
!----- Arguments -----------------------------------------------------------------------!
type(sitetype) , target :: csite
integer , intent(in) :: lsl
integer , intent(in) :: ipaa
integer , intent(in) :: ipaz
!----- Local variables. ----------------------------------------------------------------!
integer :: ipa
!----- External functions. -------------------------------------------------------------!
real , external :: compute_water_storage
real , external :: compute_energy_storage
real , external :: compute_co2_storage
!---------------------------------------------------------------------------------------!
do ipa=ipaa,ipaz
!------------------------------------------------------------------------------------!
! Computing the storage terms for CO2, energy, and water budgets. !
!------------------------------------------------------------------------------------!
csite%co2budget_initialstorage(ipa) = compute_co2_storage(csite,ipa)
csite%wbudget_initialstorage(ipa) = compute_water_storage(csite,lsl,ipa)
csite%ebudget_initialstorage(ipa) = compute_energy_storage(csite,lsl,ipa)
end do
return
end subroutine update_budget
!==========================================================================================!
!==========================================================================================!
I get error messages along the lines of
budget_utils.f90:20.54:
real , external :: compute_co2_storage
1
Error: Dummy argument 'csite' of procedure 'compute_co2_storage' at (1) has an attribute that requires an explicit interface for this procedure
(I get a bunch of them, but they are essentially all the same). Now, looking at ed_state_vars.f90 (which is "used" in the subroutine), I find
!============================================================================!
!============================================================================!
!---------------------------------------------------------------------------!
! Site type:
! The following are the patch level arrays that populate the current site.
!---------------------------------------------------------------------------!
type sitetype
integer :: npatches
! The global index of the first cohort in all patches
integer,pointer,dimension(:) :: paco_id
! The number of cohorts in each patch
integer,pointer,dimension(:) :: paco_n
! Global index of the first patch in this vector, across all patches
! on the grid
integer :: paglob_id
! The patches containing the cohort arrays
type(patchtype),pointer,dimension(:) :: patch
Etc etc - this goes one for another 500 lines or so.
So to get to the point, it seems like the original subroutine needs an explicit interface for its procedures in order to be able to use the (dummy) argument csite. Again, I am SO NEW to Fortran, but I am really trying to understand how it "thinks". I have been searching what it means to have an explicit interface, when (and how!) to use it etc. But I can't figure out how it applies in my case. Should I maybe use a different compiler (Intel?). Any hints?
Edit: So csite is declared a target in all procedures and from the declaration type(site type) contains a whole bunch of pointers, as specified in sitetype. But sitetype is being properly used from another module (ed_state_vars.f90) in all procedures. So I am still confused why it gives me the explicit interface error?
"explicit interface" means that the interface to the procedure (subroutine or function) is declared to the compiler. This allows the compiler to check consistency of arguments between calls to the procedure and the actual procedure. This can find a lot of programmer mistakes. You can do this writing out the interface with an interface statement but there is a far easier method: place the procedure into a module and use that module from any other entity that calls it -- from the main program or any procedure that is itself not in the module. But you don't use a procedure from another procedure in the same module -- they are automatically known to each other.
Placing a procedure into a module automatically makes its interface known to the compiler and available for cross-checking when it is useed. This is easier and less prone to mistakes than writing an interface. With an interface, you have to duplicate the procedure argument list. Then if you revise the procedure, you also have to revise the calls (of course!) but also the interface.
An explicit interface (interface statement or module) is required when you use "advanced" arguments. Otherwise the compiler doesn't know to generate the correct call
If you have a procedure that is useed, you shouldn't describe it with external. There are very few uses of external in modern Fortran -- so, remove the external attributes, put all of your procedures into a module, and use them.
I ran into the same problems you encountered whilst I was trying to install ED2 on my mac 10.9. I fixed it by including all the subroutines in that file in a module, that is:
module mymodule
contains
subroutine update_budget(csite,lsl,ipaa,ipaz)
other subroutines ecc.
end module mymodule
The same thing had to be done to some 10 to 15 other files in the package.
I have compiled all the files and produced the corresponding object files but now I am getting errors about undefined symbols. However I suspect these are independent of the modifications so if someone has the patience this might be a way to solve at least the interface problem.

How to explicitely use inherited variables in Fortran?

I have a question regarding best practices of model/variable usage:
Let's assume I have a module containing a few variable/parameter definitions and some subroutines that use these variables.
I do not need to explicitly use these variables in the subroutines since they are inherited from the parent module - but would it be better practice to do so?
Example:
module test
implicit none
integer, parameter :: a = 1
real :: x
contains
subroutine idk(y,z)
real, intent(in) :: y
real, intent(out) :: z
if(a .eq. 1) then
z = x*y + 5.
else
z = x*y - 5.
end if
end subroutine idk
end module test
The above example should work just fine but would it be better to add
use test, only: a,x
to the declaration part of subroutine idk?
In my reasoning, there are two main points here:
1) Pro: Explicitly adding this line let's me easily see which variables are actually needed in the subroutine.
In many cases, the module contains quite a number of variables but only a few are needed in each subroutine. So for reasons of better comprehensibility, it would be beneficial to add this line.
BUT
2) Contra: In quite a few cases, one needs a lot of the variables/parameters declared above (sometimes numbering more than 100 parameters). Explicitly using these at the beginning of the subroutine just unnecessarily clutters the code, reducing the readability of the code.
Point 1 matters mostly if only a few variables need to be included, whereas point 2 is only important if many variables need to be included. But I think it would be silly to do one thing for few variables and another for many - once you have picked a convention, you should stick to it IMHO...
Is there a best practice regarding this?
Addition:
Alternatively, one could declare the subroutine as
subroutine idk(b,w,y,z)
and then call it as idk(a,x,y,z).
On the one hand, this would give me greater flexibility if I later decide that I want to use idk with other variables.
On the other hand, it also increases the risk of mistakes if I change something later (say, I realize I don't need parameter a as a condition but parameter c. In the first cases, I simply switch out a -> c in the subroutine. But in the last case, I need to change every call to idk(c,...). If there are a lot of these calls, this is prone to mistakes)
I would really appreciate your input! Thank you!
There is absolutely no reason to use the module currently being defined. It is illegal. It may happen to compile if the module was compiled before and the compiler can find the .mod file, but file, but other than that it is wrong.
You should expect error such as
ifort -c assoc.f90
assoc.f90(10): error #6928: The module-name on a USE statement in a program unit cannot be the name of any encompassing scoping unit. [TEST]
use test
------^
The module subroutine gets the variables from the host module through host association and the use statement is for use association. These are two different things and should not be mixed.
If you want to avoid global variables, pass them as arguments. This is a general advice. What is best depends on each case and the programmer and cannot be answered generally.

Host Association vs Use Association in Fortran

Are there any "general rules" as to when one is preferable to the other?
The context of this question is: I asked a different question regarding host association yesterday (link) and in the comments, I was advised to use host association with caution. The reason being that through host association, it is easy to inadvertently modify variables since the subroutines have unrestricted access to all variables that are declared in the module.
To illustrate this, I will use the following code example:
module mod
implicit none
real :: x
contains
subroutine sub(y)
use other_mod, only: a
real, intent(out) :: y
y = a + x
a = a + 1.
x = x + 1.
end subroutine sub
end module mod
Both aand x are modified in sub. But for x, I need to go through all the code to see this. That a is used in sub (and possibly modified) can be seen easily by looking at the declaration part of sub.
In this sense, it seems preferable to have two kinds of modules:
A module or modules only containing variable declarations (which are then used when needed)
Modules that only contain procedures and possibly parameter declarations but no variable declarations
This gets rid of host association for variables altogether.
But this doesn't seem practical for a number of reasons:
I might have a dozen subroutines using (and modifying) the same variables in one module. Having to use these variables everytime clutters the code, especially if there are a lot of them (say a few hundred).
Seperating the declaration of a variable from where it is actually used seems to make the code less comprehensible:
Either, one creates one giant control file containing all the declarations. This could be quite confusing if the code is large and uses many variables.
Or, one creates a seperate control file for every module (or group of modules, if they depend on the same content). This would make the code itself better comprehensible, since using the variables immediately shows where they are coming from. But it would complicate the structure of the code, creating a vastly more complicated file structure (and accompanying dependency structure).
In the end, all of this boils down to: When is it more sensible to put the declaration of variables in the same module in which they are used (so that they are used by host association) and when is it more sensible to outsource the declaration to a seperate module (so that the variables will be used via use association when they are needed)?
Are there any general guidelines or should this be decided on a case by case basis? And if it is case by case, what are the reasons to go for one over the other?
Fortran provides several ways to create, store, use, and pass data between different "program units": the main program, external procedures, and modules.1 As you know, each program unit can contain internal procedures - which, through host association, have access to any variable or procedure contained within the host. This is often seen as an advantage. As mentioned already by #HighPerformanceMark in his comment, the general guideline for when to use host-association or use-association is:
use host-association when variables are only (or mainly) used by routines declared in the same module, and use use-association when you want to define variables to be used in many modules
From your comments, it sounds like most or all of the host variables in your main program are accessed by each internal procedure (about a dozen or so subroutines). If that's the case, then host-association seems like a very reasonable option, and there's really no need to pass in arguments to each subroutine explicitly. On the other hand, if each subroutine actually uses only a subset of the variables, then it might be reasonable to get more explicit about it.
Like you, I am generally uncomfortable with using variables within a procedure that haven't been declared in an argument list. This is partly because I like how the list of args is self-documenting, and it helps me to reason about the code and how data is manipulated within it. This is even more true when collaborating with other workers, or if I've spent some time away from the code and my memory of it has faded. However, I've discovered there is little reason to avoid host association altogether, as long as you are aware of how it works and have a strategy.
In fact, I tend to use internal procedures and host-association quite often, especially for short functions/subroutines. I find it helpful to loosely think of the host as the "object", its variables as "attributes", and any internal procedures very much like the object's "methods" that do the work. Of course, that's simplifying things, but that's really the point.
For more complex programs I reduce the amount of host-association from the "main" program itself, which then exists primarily to call the various subroutines in the proper order and context. In this case, we can take advantage of use-association and choose to use module entities (such as procedures, variables, types, parameters) directly within the program unit that needs them. We can further restrict access to only those module entities that are needed with only:. This aids readability, the data flow is clearly indicated, and I find that updating the code later is more straightforward. You know, inheritance, encapsulation, and whatnot...but Fortran style. Which is actually pretty good.
Here's an example program structure that works for me and the moderately-sized projects I've worked on in Fortran. I like to keep my widely-used (static) parameters in a separate module (or modules, if grouped according to function). I keep derived types and type-bound procedures in another separate module(s). If it's useful, I make certain module entities private, so that they are not accessible from other program units. And I guess that's it.
module params
implicit none
public !! All items public/accessible by default.
integer, parameter :: dp = kind(0.d0)
integer, parameter :: nrows = 3
real(dp), parameter :: one=1.0_dp, two=2.0_dp
...
end module params
module types
use params, only: dp, nrows
implicit none
public !! Public by default.
private :: dim2
...
integer, parameter :: dim2 = 3
...
type :: A
integer :: id
real(dp), dimension(nrows,dim2) :: data
contains
procedure, pass :: init
end type A
...
contains
subroutine init(self, ...)
...
end subroutine init
...
end module types
module utils
implicit none
private !! Private by default.
public :: workSub1, workSub2, subErr
...
integer,save :: count=0 !! Accessible only to entities in this module.
...
contains
subroutine workSub1(...)
...
end subroutine workSub1
subroutine workSub2(...)
...
end subroutine workSub2
subroutine subErr(...)
...
end subroutine subErr
end module utils
program main
!! An example program structure.
use params, only: dp
implicit none
real(dp) :: xvar, yvar, zvar
integer :: n, i
logical :: rc
call execute_work_subroutines()
contains !! Internal procs inherit all vars declared or USEd.
subroutine execute_work_subroutines()
use types, only: A
type(A) :: DataSet
!! begin
call DataSet%init(i)
do i = 1,n
call workSub1(xvar,yvar,zvar,A,i,rc)
if (rc) call subErr(rc)
call workSub2(A,rc)
if (rc) call subErr(rc)
enddo
end subroutine execute_work_subroutines
end program main
1There are also submodules, but I am not familiar with them and don't want to give misleading info. They do seem useful for logically separating large modules.

Class() pointer to a pointer in Fortran: odd behaviour

I've had a good look around the previous posts and I don't think that this topic has been covered, hopefully somebody can help.
I'm writing a code in fortran 2003, and using ifort. I have the following types which I need to manipulate, which I have design to give the flexibility that I need:
module parameters
double precision, target :: cur_x(3)
type fundamental
double precision, pointer :: x => null()
end type fundamental
type, extends(fundamental) :: ion
class(fundamental), pointer :: core => null()
end type ion
SAVE
end module parameters
The idea being that I build up a kind of a linked list of particles by using the previous in the list as the core of the next. Note that in reality I will have a large number of extensions to 'fundamental', all of which can be the 'core' of other particles. I want the calculated quantities, x, to be in an array together in physical memory as I will be addressing subsets of them in fairly complicated ways, for which I want to use another set of pointers to cur_x
The initialisation of the code goes like this, where I have added some diagnostic lines:
use parameters
type(fundamental), target :: electron, proton
type(ion), target :: hydrogen
write(*,*)associated(electron%x),associated(proton%x), &
& associated(hydrogen%core),associated(hydrogen%core%x)
electron%x => cur_x(1)
hydrogen%core => proton
proton%x => cur_x(2)
hydrogen%x => cur_x(3)
cur_x = 1.0
write(*,*)electron%x,proton%x,hydrogen%x,hydrogen%core%x
which prints
F F F T
1.0 1.0 1.0 <garbage>
Where I expect proton%x and hydrogen%core%x to be the same address in memory (cur_x(2)). So I have two questions
I have initialised all my pointers to be null. Why does
associated(hydrogen%core%x) give true? If I try and nullify this
pointer at the top of the code I get inconsistent results; using
nullify(hydrogen%core%x)
results in a segmentation fault. Performing
hydrogen%core%x => null()
allows the code to run, but associated(hydrogen%core%x) remains true
I have made sure to associate the list of pointers from parent to child, as suggested in this summary of surprising errors in fortran. The fact that proton%x is working but hydrogen%core%x gives garbage is something I don't understand.
I can work around the problem but this would sacrifice the generality that I will need for more complex calculations. I would also quite like to understand what is going wrong here.
Thanks for your help!
Jim
EDIT: added in 'target' properties for various things; note that this were always in the code, i just forgot them in transferring to this post
EDIT: To clarify, my main issue with the above code is that the final write command gives an uninitialised output for hydrogen%core%x, even following the association commands after the first write. Even though I initialise core as null in my type definitions, there seems to be a problem with it; and if I try and nullify it at the top of the code the program crashes.
The basic problem is that hydrogen%core is not associated. The effect of associated(hydrogen%core%x) is therefore indeterministic. You just can not access/query a field (x) of a derived type pointer (hydrogen%core), if the pointer is not associated e.g. points to null() instead of an existing derived type instance in memory. Your compiler may generate a code, which does not immediately crash when you try it, but whatever is done after that is indeterministic, as you probably have already overwritten some data at random memory address.
Actually, I compiled a self-containing version of your code (see below) with various compilers and I got immediate segfaults at the first write statement. Using appropriate check options one of the binaries even reports the reason being in referencing the disassociated pointer hydrogen%core. If you comment out the problematic associated() query (as in the code below) all binaries run fine.
Also, please note, that the variables electron and proton must have the target attribute, otherwise the code should not even compile at all. If your compiler compiles the code without complaints, you should probably think about changing to an other one.
module parameters
implicit none
save
type :: fundamental
double precision, pointer :: x => null()
end type fundamental
type, extends(fundamental) :: ion
class(fundamental), pointer :: core => null()
end type ion
end module parameters
program test
use parameters
implicit none
type(fundamental), target :: electron, proton
type(ion) :: hydrogen
double precision, target :: cur_x(3)
! If you remove the comment in the next statement, the program will be indeterministic
! and probably crash.
write(*,*) associated(electron%x),associated(proton%x), &
& associated(hydrogen%core)!, associated(hydrogen%core%x)
electron%x => cur_x(1)
hydrogen%core => proton
proton%x => cur_x(2)
hydrogen%x => cur_x(3)
cur_x(:) = 1.0
write(*,*)electron%x,proton%x,hydrogen%x,hydrogen%core%x
end program test
If hydrogen%core is not associated, then it is a programming error to reference (or define) hydrogen%core%x as you do so in the first write statement. With that programming error present, anything goes from that point on.
You don't say what version of ifort you are using but there have been (and I think are extant, if I recall recent posts on the Intel forums) compiler bugs to do with polymorphic pointers.
That aside, for hydrogen%core to be pointed at the local proton variable, then proton must have the TARGET attribute. I would expect the compiler to diagnose this.

Are local variables in Fortran 77 static or stack dynamic?

For my programming languages class one hw problem asks:
Are local variables in FORTRAN static or stack dynamic? Are local variables that are INITIALIZED to a default value static or stack dynamic? Show me some code with an explanation to back up your answer. Hint: The easiest way to check this is to have your program test the history sensitivity of a subprogram. Look at what happens when you initialize the local variable to a value and when you don’t. You may need to call more than one subprogram to lock in your answer with confidence.
I wrote a few subroutines:
- create a variable
- print the variable
- initialize the variable to a value
- print the variable again
Each successive call to the subroutine prints out the same random value for the variable when it is uninitialized and then it prints out the initialized value.
What is this random value when the variable is uninitialized?
Does this mean Fortran uses the same memory location for each call to the subroutine or it dynamically creates space and initializes the variable randomly?
My second subroutine also creates a variable, but then calls the first subroutine. The result is the same except the random number printed of the uninitialized variable is different. I am very confused. Please help!
Thank you so much.
In Fortran 77 & 90/95/2003, if you want the value of a variable local to a subroutine preserved across subroutine calls, you should declare it the "save" attribute, e.g., (using Fortran 90 style):
integer, save :: counter
OR
integer :: counter
save :: counter
.
Or, if you want the "save" behavior to apply to all variables just include in the subroutine a simple
save
statement without any variables.
In Fortran 90, a variable initialization in a declaration,
integer :: counter = 0
automatically acquires the save attribute. I don't think that this was the case in Fortran 77.
This is one area in which experiments could be misleading -- they will tell you what a particular compiler does, but perhaps not what the Fortran 77 language standard is, nor what other compilers did. Many old Fortran 77 compilers didn't place local variables on the stack and implicitly all variables had the save attribute, without the programming having used that declaration. This, for example, was the case with the popular DEC Fortran compilers. It is common for legacy Fortran 77 programs that were used only with a particular compiler of this type to malfunction with a modern compiler because programmers forgot to use the save attribute on variables that needed it. Originally this didn't cause a problem because all variables effectively had the save attribute. Most modern compilers place local variables without save on the stack, and these programs frequently malfunction because some variables that need "save" "forget" their values across subroutine calls. This can be fixed by identifying the problem variables and adding save (work), adding a save statement to every subroutine (less work), or many compilers have an option (e.g., -fno-automatic in gfortran) to restore the old behavior (easy).
It seems a peculiar question -- you won't find out about "Fortran 77" but about a particular compiler. And why use Fortran 77 instead of Fortran 95/2003? Does the prof. think Fortran stopped in 1977?
To amplify on one point that #MSB made;
Fortran standards do not tell compiler-writers how to implement the standards, they are concerned with the behaviour of programs visible to the programmer. So the answer to the question is 'it all depends on the compiler'. And OP does not tell us which compiler(s) (s)he is using.
Furthermore, if you trawl back through the mists of time to examine all the FORTRAN77 compilers ever written, I am confident that you will find a wide variety of different implementations of the features you are interested in, many of them tied to quite esoteric hardware architectures.