Incorrect values from common block - fortran

How can I create a link between routine and sub-program using Fortran?
Program Example
common a,b,c,d,e
print*,"Enter a"
read*,a
print*,"Enter coefficient of x in f1(x)"
read*,b
print*,"Enter intercept in f1(x)"
read*,c
print*,"Enter coefficient of x in f2(x)"
read*,d
print*,"Enter intercept in f2(x)"
read*,e
Print*,f1(2.),f2(3.)
pause
end
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function f1(x)
common a,b,c
f1=a*x**2+b*x+c
return
end
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function f2(y)
common d,e
f2=d*y+e
return
end
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
this was an example.
when I print the f1(2.) and f2(3.) I get true result for the first one and false results for the second one.

There are two very different questions in your post.
How do we share data between subprograms? In modern Fortran use modules. We have many questions and answers about that. Common blocks are obsolete (and since Fortran 2018 officially obsolescent - Thanks #steve).
Why are the results using common incorrect?
You are using an unnamed common block. In comon blocks the variable names are irrelevant. They can differ arbitrarily between compilation units (main program, subprograms). The order is important.
Therefore your
common d,e
is the same as doing
common a,b
To get access to the fifth element of the common block you must have all five variables
common a,b,c,d,e
(or as francescalus points out, one has to reference the right numerical storage unit. Ome could also have one array instead.)
Finally, I would like the stress the importance of implicit none. You should really use it.

Related

Where does this Fortran variable come from?

Can anyone tell me about the costh variable used in the following subroutine? From where is the subroutine obtaining the value of this variable? Is it some error or inbuilt function?
The complete subroutine is given below.
SUBROUTINE MOMENT(I,A,AP,MODE,EP,NCASC,ID)
COMMON/MOM/VY(99996),VZ(99996),VX(99996)
DIMENSION ERES(99996),FCT(99996)
COMMON/XQANG/SUM(300,10),MDIR,COSTH
EQUIVALENCE(ERES(1),VY(1)),(FCT(1),VZ(1))
IF(ID-2)10,30,40
C INITIALIZATION
10 N=1
NN=N+NCASC-1
DO 20 J=N,NN
VY(J)=EP*MDIR
VX(J)=0.
20 VZ(J)=EP*(1-MDIR)
GO TO 60
C
C CALCULATION OF MOMENT
C
CKM 30 RN4=RANF(0.)
30 RN4=RAN(ISEED) !KM
PHI=6.28318*RN4
SOX=2.*AP*EP/(A**2*931.5)
C BUG FIX A*(AP+A)REPLACED BY A**2 12/15/82
C IF(SOX.LT.0.)WRITE(*,943)AP,EP,A
VT=SQRT(SOX)
SOX=1.-COSTH**2
IF(SOX.LT.0.)SOX=0.
SINTH=SQRT(SOX)
VZSE=VT*COSTH
VYSE=VT*SINTH*SIN(PHI)
VXSE=VT*SINTH*COS(PHI)
VZ(I)=VZ(I)+VZSE
VY(I)=VY(I)+VYSE
VX(I)=VX(I)+VXSE
VZP=VZ(I)-VZSE*(A/AP+1.)
VYP=VY(I)-VYSE*(A/AP+1.)
VXP=VX(I)-VXSE*(A/AP+1.)
VPP2=VZP*VZP+VYP*VYP+VXP*VXP
EPART=AP*VPP2*469.
SOX=0.
IF(VPP2.GT.0.0)SOX=VZP/SQRT(VPP2)
C DO NOT USE QUICK FUNCTIONS HERE
ANG=ACOS(SOX)*180./3.1415927
CALL OUTEM(2,MODE,EPART,ANG)
GO TO 60
C
C END CALCULATION
C
40 VFTS=VX(I)**2+VY(I)**2+VZ(I)**2
ERES(I)=0.5*A*VFTS*931.5
IF(VFTS.NE.0.)GO TO 50
FCT(I)=0.0
GO TO 60
50 FCT(I)=ACOS(VZ(I)/SQRT(VFTS))*180./3.1415927
60 RETURN
END
This line
COMMON/XQANG/SUM(300,10),MDIR,COSTH
informs the subroutine about a common block called XQANG which has an element called COSTH. In the absence of other information, and in a code of that vintage, this is most likely to be a real variable.
Common blocks are an early-Fortran mechanism for sharing variables across program units, such as between a main program and a subroutine. In straightforward use the same common block declaration will be found in multiple locations, with the same list of variables. Each declaration refers to the same variables.
There is a twist though, and one to watch out for carefully. The common block is actually a shared block of memory, and there is no requirement that each instance of the declaration identify the same variables. One common use of common blocks was to declare, say, an array of 100 reals in one location, but to declare two arrays each of 50 reals elsewhere -- same memory, different variables.
Even better, they could also be used to change the types of variables (sort of). One usage of a common block might contain a real variable occupying 4 bytes, while another usage of the same block might contain a 4-byte integer variable at the same location - same bits, different interpretations.
These twists are among the reasons for common blocks being widely deprecated. Another reason for their deprecation is that they obscure the sharing of variables, these days most of us prefer to explicitly pass arguments into and out of subroutines through their argument lists.
I'd guess very few Fortran programmers under 50 are still writing new code using them. But Fortran programmers from 8 - 80 are still working on codes containing them.

Is the storage of COMPLEX in fortran guaranteed to be two REALs?

Many FFT algorithms take advantage of complex numbers stored with alternating real and imaginary part in the array. By creating a COMPLEX array and passing it to a FFT routine, is it guaranteed that it can be cast to a REAL array (of twice the size) with alternating real and imaginary components?
subroutine fft (data, n, isign)
dimension data(2*n)
do 1 i=1,2*n,2
data(i) = ..
data(i+1) = ..
1 continue
return
end
...
complex s(n)
call fft (s, n, 1)
...
(and, btw, is dimension data(2*n) the same as saying it is a REAL?)
I'm only writing this answer because experience has taught me that as soon as I do write this sort of answer one of the real Fortran experts hereabouts piles in to correct me.
I don't think that the current standard, nor any of its predecessors, states explicitly that a complex is to be implemented as two neighbouring-in-memory reals. However, I think that this implementation is a necessary consequence of the standard's definitions of equivalence and of common. I don't think I have ever encountered an implementation in which a complex was not implemented as a pair of reals.
The standard does guarantee, though that a complex can be converted into a pair of reals. So, given some definitions:
complex :: z
complex, dimension(4) :: zarr
real :: r1, r2
real, dimension(8) :: rarr
the following will do what you might expect
r1 = real(z)
r2 = aimag(z)
Both those functions are elemental and here comes a wrinkle:
real(zarr)
returns a 4-element array of reals, as does
aimag(zarr)
while
[real(zarr), aimag(zarr)]
is an 8-element array of reals with the real parts of zarr followed by the complex parts. Perhaps
rarr(1:8:2) = real(zarr)
rarr(2:8:2) = aimag(zarr)
will be OK for you. I'm not sure of any neater way to do this though.
Alexander's not the only one able to quote the standard ! The part he quotes left me wondering about non-default complex scalars. So I read on, and I think that para 6 of the section he points us towards is germane
a nonpointer scalar object of any type not specified in items (1)-(5)
occupies a single unspecified storage unit that is different for each
case and each set of type parameter values, and that is different from
the unspecified storage units of item (4),
I don't think that this has any impact at all on any of the answers here.
To append to Mark's answer this is indeed stated in the Standard: Clause 16.5.3.2 "Storage sequence":
2 In a storage association context
[...]
(2) a nonpointer scalar object that is double precision real or
default complex occupies two contiguous numeric storage units,
emphasis mine.
As for storage association context: Clause 16.5.3.1 "General" reads
1 Storage sequences are used to describe relationships that exist
among variables, common blocks, and result variables. Storage
association is the association of two or more data objects that occurs
when two or more storage sequences share or are aligned with one or
more storage units.
So this occurs for common blocks, explicit equivalence, and result variables. As Mark's said, there is no explicit statement for the general case.
My guess is, that it is most convenient to follow this always to ensure compatibility.
Thanks to IanH to pointing this out!
No, as far as I know.
You can have storage association between a real single precision array and a complex single precision array by EQUIVALENCE, COMMON, and ENTRY statement.
But in general you cannot pass a complex array to a subroutine that expects a real array.

Fortran : Initialize all variables to a specific default value

I am working on a ~40 years old Fortran spaghetti code with lots of variables that are implicitly declared. So there is not a simple way to even know what variables exist in the code in order to initialize their values. Now, is there a way to tell the compiler (for example Intel Fortran) to initialize all variables in the code to a specific default value (e.g., -999) other than zero or a very large number, as provided by Intel compiler?
gfortran provides some options for this. Integers can be intialized with -finit-integer=n where n is an integer. For real numbers you can use -finit-real=<zero|inf|-inf|nan|snan>. Together with -ffpe-trap=denormal this can be very helpful, to get uninitialized reals.
You probably want :
ifort -check uninit
Note per the man page this only checks scalars
Also, based on some quick testing it is a pretty weak check. It doesn't catch this simple thing for example:
program test
call f(i)
end
subroutine f(j)
write(*,*)j
end
returns 0 ..
I suppose its better than nothing though.

Why would common block variables not preserve their values?

First, I know that using common blocks is a bad idea in fortran (and programming in general). However, I'm updating someone else's code and I don't want to mess up things that are known to work.
Second, I know I should post something more specific then this. If I knew how to reduce this into something small, I would. However, since I know, and I don't think you'll appreciate 2500 lines of code, I can't post a specific example.
With that in mind, I can't describe my problem.
I'm updating someone else's fortran code. The guy used several (4) common blocks to set up global variables. For some reason when I call a function that use such a block, all it's value are 0. Has anyone encountered that before? Does anyone know why this might happen? How to reproduce this? Any starting point to check this would be helpful.
For what it worth, the said common block is declared as
common /set/ block,x,y,z,llx,lly,llz,ilx,ily,ilz,third,third2
block is a 4D array. x, y, and z are 1D array. llx,lly, and llz, are double precision types. The rest are integer types.
The common block(s) is (are) declared and initialized at the main program before any function is called.
Some compilers do initialize common variables to zero, so if you first invoke the function with the common block, you might find zeros everywhere (although you should not rely on that). But once you set some values for the common block variables in the program, those values should appear whenever you use the common block.
As of the variables in the common block: They can be of arbitrary type, as long as they are consistently defined at all places, where the common block is used.
Can you compare your code with this tiny example? I think you might be missing something, like the "common" declaration inside the subroutine.
Note that you don't need to use the same name for the variable inside the subroutine (AA) as you have for main (GB). Just the common block name (myarray) has to be the same. However, nothing bad will happen if you replace AA by GB, and the final result would be a little bit cleaner to read.
program main
real GB(4)
common /myarray/ GB
integer i
real B(4)
GB=0
write(*,*) 'GB',GB
do i=1,4
call AddSubR()
write(*,*) 'GB',GB
enddo
end program main
subroutine AddSubR()
real AA(4)
common /myarray/ AA
integer i
do i=1,4
AA(i) = AA(i)+1
enddo
end subroutine AddSubR

Common block usage in Fortran

I'm new to Fortran and just doing some simple things for work. And as a new programmer in general, not sure exactly how this works, so excuse me if my explanation or notation is not the best. At the top of the .F file there are common declarations. The person explaining it to me said think of it like a struct in C, and that they are global. Also in that same .F file, they have it declared with what type. So it's something like:
COMMON SOMEVAR
INTEGER*2 SOMEVAR
And then when I actually see it being used in some other file, they declare local variables, (e.g. SOMEVAR_LOCAL) and depending on the condition, they set SOMEVAR_LOCAL = 1 or 0.
Then there is another conditional later down the line that will say something like
IF (SOMEVAR_LOCAL. eq. 1)
SOMEVAR(PARAM) = 1;
(Again I apologize if this is not proper Fortran, but I don't have access to the code right now). So it seems to me that there is a "struct" like variable called SOMEVAR that is of some length (2 bytes of data?), then there is a local variable that is used as a flag so that later down the line, the global struct SOMEVAR can be set to that value. But because there is (PARAM), it's like an array for that particular instance? Thanks. Sorry for my bad explanation, but hopefully you will understand what I am asking.
Just to amplify something #MSB already mentioned: COMMON blocks tell a compiler how to lay variables out in memory. There is almost no reason to use them with modern Fortran, ie with any compiler which can cope with Fortran 90 or later, and there are good reasons to avoid them.
And to add one thing: in modern Fortran you can do approximately what C structs do with user defined types. Check your documentation for TYPE.
The first declaration has SOMEVAR as a scalar integer of two bytes. The usage you show has SOMEVAR has an array -- based on it being indexed. This is possible to do in Fortran via "sequence association" but it is poor practice. In one file you could declare SOMEVAR as INTEGER*2 and two bytes are allocated to this scalar. In another file you could declare it as INTEGER*1 SOMEVAR(2), and two bytes are reserved, this time for an array of two elements, each of one byte. Using the same common block in both files can cause these two variables to overlap, byte by byte -- sequence association. Many years ago, when memory was very small, programmers did this to reduce memory usage, knowing that different subroutines were using variables at different times. The reasons to do this today are very, very limited. Mostly one shouldn't because it is liable to be confusing.
You can also setup sequence association with the EQUIVALENCE statement. Again, best avoided. The modern replacement for the times that one must do "tricky" things that needed the EQUIVALENCE statement is the TRANSFER function.