How Declare Global variables [duplicate] - fortran

This question already has an answer here:
How to avoid declaring and setting the value of a variable in each subroutine?
(1 answer)
Closed 5 years ago.
I have a program that calls functions within the same program but I want to declare and initialize the variables on the top and access them at the end of the program.
!Declaration
INTEGER TOPCHORD,BOTCHORD, SUPPS, PURLINS;
!Initialization
! Define Layers for connecting lines
TOPCHORD = 32
BOTCHORD = 32
SUPPS = 36
PURLINS = 30
INTEGER FUNCTION IFLANGE1(IEND1,IEND2,ISUP)
IFLANGE1=TOPCHORD
SELECT CASE(IEND1)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
SELECT CASE(IEND2)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
RETURN
END
I get error that variable 'SUPPS' referenced but not set

You might want to have a look at the documentation - you're missing a couple of important statements. (Also try to always include implicit none -- this is very helpful for catching certain issues).
A slightly modified code that should compile is
!Declaration
INTEGER TOPCHORD,BOTCHORD, SUPPS, PURLINS;
!Initialization
! Define Layers for connecting lines
TOPCHORD = 32
BOTCHORD = 32
SUPPS = 36
PURLINS = 30
contains !Indicate that the program unit contains other procedures
INTEGER FUNCTION IFLANGE1(IEND1,IEND2,ISUP)
IFLANGE1=TOPCHORD
SELECT CASE(IEND1)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
SELECT CASE(IEND2)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
RETURN
END FUNCTION !End the function definition
END !This is a required end statement to say we've reached the end of the program
This isn't the nicest style etc. but has the minimum number of changes to compile.
For any slightly more complex program I would strongly recommend using modules for storing variables (and also procedures) that you want to access from different parts of the code.

Related

Fortran "Cannot assign to a named constant at (1)" in if statement

Here's what I'm trying to run:
if (z.le.zstart) then
if (y.ge.((6.95*wg_y2)/5)).and.(y.le.((12.55*wg_y2)/5)) then
indexmedia=nd
end if
end if
For context,
zstart is an arbitrary line of constant y.
wg_y2 = 5e-6
And for some reason it doesn't like the (y.ge.((6.95*wg_y2)/5)) bit, as the (1) was placed at the end of that bit.
I had a suspicion that it doesn't like anything that isn't an integer in the if statement but I changed 6.95 to 7 and 12.55 to 13 and it still didn't like it. Perhaps it needs to end up resolving to an integer?
I need these parameters to end up to
6.95 < y < 12.55 though.
Is there a workaround for this?
When compiling the code (not nice as I didn't declare the variables!, but that isn't the problem here so I abstain from it to keep it a bit small):
program tst
if (z.le.zstart) then
if (y.ge.((6.95*wg_y2)/5)).and.(y.le.((12.55*wg_y2)/5)) then
indexmedia=nd
end if
end if
end
one gets the error:
aa.f90:3:29:
if (y.ge.((6.95*wg_y2)/5)).and.(y.le.((12.55*wg_y2)/5)) then
1
Error: Cannot assign to a named constant at (1)
aa.f90:6:3:
end if
1
Error: Expecting END PROGRAM statement at (1)
This is due to a missing pair of round brackets in the line:
if (y.ge.((6.95*wg_y2)/5)).and.(y.le.((12.55*wg_y2)/5)) then
which should read
if ((y.ge.((6.95*wg_y2)/5)).and.(y.le.((12.55*wg_y2)/5))) then

Parse error, unexpected ',',expecting '=' [duplicate]

I wrote the following two lines in fortran
C23456789
REAL H3 = 0
H3=H*H*H
and I received the following errors from gdb :
ljmd.f:186.5:
REAL H3 = 0
1
Error: Non-numeric character in statement label at (1)
ljmd.f:187.5:
H3=H*H*H
1
Error: Non-numeric character in statement label at (1)
ljmd.f:187.6:
H3=H*H*H
1
What is the proper way to create and use new variables in the middle of someone else's fortran program? C23456789 is my label of the current column used in the program.
This is in any random Fortran tutorial. I expect you have the fixed source form. Then any statement must start at column 7 or farther.
Also,
REAL H3 = 0
isn't legal in free form source Fortran and does a completely different thing in fixed form (see #francesalus' comment). And in your case there is no reason to initialize the variable at all. You can just do
REAL H3
H3 = H**3
If you happen to need the initialization somewhere else, you either must use
real :: a = 0
(requires Fotran 90), or
REAL A
DATA A/0/
(in Fortran77). Beware, both version make the variable SAVE which you may know as static from other languages.
The last point, you cannot introduce variables anywhere "in the middle of program", the declaration of variables have their place at the beginning of each compilation unit (program, function, subroutine,...).

Rainflow algorithm - Fortran conversion to Matlab

I am trying to convert a Rainflow cycle counting algorithm which is in Fortran, which is a language I am not familiar with, into Matlab.
There is a ready made Rainflow I've downloaded for Matlab but that does not fit the requirements of my project so I'm trying to build one from scratch.
Here is the Fortran code:
INTEGER BUFFER (4096), INDEX, VALUE, RANGE, MEAN, X, Y
INDEX = 0
10 CONTINUE
call 'get next peak/valley', VALUE
INDEX = INDEX + 1
BUFFER (INDEX) = VALUE
20 CONTINUE
IF (INDEX.LT.3) THEN
not enough points to form a cycle
GOTO 10
ELSE
X = ABS (BUFFER(INDEX) - BUFFER(INDEX - 1))
Y = ABS (BUFFER(INDEX - 1) - BUFFER(INDEX - 2))
IF (X.GE.Y) THEN
c -- cycle has been closed
RANGE = Y
MEAN = (BUFFER(INDEX-1) + BUFFER(INDEX-2))/2
c -- remove the cycle
INDEX = INDEX - 2
BUFFER(INDEX) = BUFFER(INDEX+2)
c -- see if this value closes any more cycles
GOTO 20
ELSE
GOTO 10
END IF
END IF
I had downloaded f2matlab (a Fortran to Matlab converter) but it requires a Fortran compiler which I do not have.
The bits I don't really understand how I can convert are:
The call 'get next… line (is this an input()?)
The BUFFER(4096) etc (is this a bit large to be a matrix in matlab?)
The GOTO/CONTINUE structure.
What do they mean, in English (or Matlab)?
I have seen
How to translate fortran goto state to matlab
and
translating loop from Fortran to MATLAB
but they do not help me very much.
This
call 'get next peak/valley', VALUE
isn't (currently) syntactically valid Fortran and I'm not sure whether any compiler of yore would have understood it either. I guess that it means get a VALUE for use in the following bits of code.
INTEGER BUFFER (4096)
is a simple declaration that BUFFER is a vector of 4096 integers, nothing to scare Matlab in that volume of data.
Finally, GOTO is an unconditional jump and the number following it is the label of the line to jump to, so GOTO 10 means execute the line with label 10 next. It was fairly common in FORTRAN of the vintage you are showing us to jump to a CONTINUE statement which is, in this context, a no-operation, execution continues to the next line.
In another context, with DO loops CONTINUE would have marked the end of the block of code inside the scope of the loop and would have a subtly different effect.

fortran goto scope

I have a legacy fortran code with many statements like 'goto 50'. I was wondering whether the target of goto is global or local. I mean, if multiple functions have a target '50', where does the goto leads to.
Thanks for answering.
The statement labels (eg, "50") have to be defined within the current "scoping unit", which basically translates in this context to the subroutine/function that the goto call is in (or the main program, if the call is in the main program).
So for instance, in the following program, the main program and both contained subroutines have their own label 50, and the gotos go to "their" line 50.
program testgotos
implicit none
goto 50
call second
50 call first
call second
contains
subroutine first
integer :: a = 10
goto 50
a = 20
50 print *,'First: a = ', a
end subroutine first
subroutine second
integer :: a = 20
goto 50
a = 40
50 print *,'Second: a = ', a
end subroutine second
end program testgotos
Local.
Technically from the f77 standard ( http://www.fortran.com/fortran/F77_std/f77_std.html )
"Statement labels have a scope of a program unit."

problem using formatted Fortran `write(6,*)` output

I'm currently porting an application from Fortran to C and need to output some variables to compare results. I'm very new to Fortran, and although i understand the code and have now ported several thousand lines, I'm a noob at writing Fortran code myself.
This code:
write(6,'(A,I3,A,E12.8,A,E12.8,A,E12.8,A,E12.8,A,E12.8)') 'iHyd:',
& ih,'; dzdr: ',dzdr,'; tauray:', tauRay,'; zRay: ',
& zray,'; ampRay: ',realpart(aray),'+j*',
& imagpart(aray),'; qRay: ',qray,'; width :',w
Compiles fine, but when run, the program exits with:
At line 296 of file calcpr.for (unit = 6, file = 'stdout')
Fortran runtime error: Expected INTEGER for item 15 in formatted transfer, got REAL
(A,I3,A,E12.8,A,E12.8,A,E12.8,A,E12.8,A,E12.8)
^
q0: 1432.3944878270595
nArrayR: 501 nArrayZ: 201
iHyd: 1; dzdr: ************; tauray:************; zRay: ************; ampRay: NaN+j* NaN
; qRay:
Besides being really ugly, it doesn't make much sense to me, as ìh is declared as integer*8 and not as real.
So how can i solve this?
I'm counting 6 character&variable specifications in the format statement, but you're printing 8 of them.
edit:
a nicer use of the format statement would be '(A,I3,7(A,E12.8))'
Fortran "recycles" the format if there are more things to be printed than specified in the format statement. If a write statement gives results you don't understand, to diagonose the problem it may be helpful to remove the things printed one at a time until the error goes away.
It says "item 15", which I would take to be down near the end of your list, not ih at the beginning. It's clear that both "w" and "qray" are being printed as REAL; is either one of them an INTEGER? You may need to change the format specifier then.