I'm working with fortran subroutines of a finite element analysis program. I have to share variables between the two subroutines so I'm using COMMON blocks (EDIT: module is better). The problem is that only some of the variables are passed to the other subroutine, others are not.
My code is like this:
First subroutine:
real knom, krot
COMMON /kVAR/ kmom, krot
SAVE /kVAR/
Second subroutine I use the same syntax. I'm controlling the results by writing kmom and krot values in each subroutine to a txt file:
write(6,*) 'I am in URDFIL', or 'I am in UFIELD'
1 KINC, kmom, krot
The results are:
I am in URDFIL 1 -16700 -2.3857285E-03
I am in UFIELD 2 -16700 -1155769886
So the value of krot is lost. Any advise is most welcome.
João
Solved:
module shared_var
implicit none
real*8 kmom, krot
save
end module shared_var
And in each subroutine:
use shared_var
Did you include the declaration of knom, krot in the second routine? Probably you are getting implicit typing and krot is being output as an integer. And it appears that you have a typo: knom versus kmom. That is why kmom is output as an integer in both cases -- implicit typing as an integer since knom is the real. If implicit typing is in effect these variables will be integers since they begin with "k". My strong recommendation is to not use implicit typing unless it is too much work to remove from legacy code. It is highly recommended to use "implicit none" so that the compiler will warn you if you forget to type a variable or make a typo in a variable name. Most compilers have options that are equivalent to "implicit none".
Related
I'm very new at Fortran. I'm trying to compile this Fortran, I think 90??? Code. I'm using visual studio with the intel compiler.
The following code is giving me an error 5082. I have absolutely no idea why. Like literally no clue. Please, please help.
integer function Dub(n)
integer n
Dub = 2*n
return
end
program Subroutines
implicit none
! Variables
integer n
n = 5
! Body of Subroutines
write(*,*) n
Dub(n)
write(*,*) 'Press Enter to Exit'
read(*,*)
stop
end program Subroutines
In Fortran a call to a function, or a subroutine, must be part of a statement (or an initialization expression, but that's more advanced). name(argument[s]) by itself is not a statement, unlike some other languages such as C, C++ and Java. A function call must be in an expression, and a subroutine call must use the call keyword. See https://en.wikibooks.org/wiki/Fortran/Fortran_procedures_and_functions for examples.
Changing that line of your program to n = Dub(n) would make it legal, but rather useless. That function does nothing except return a value, and your main program does nothing useful with the value returned. Generally you call a function because you want either a side effect from executing the function, or to use the returned value, or both.
I'm doing a very basic Fortran tutorial to learn it for grad school and I input the codes for conditionals and loops exactly as they were written in the tutorial but I keep getting the "unexpected end of file" error when I try to compile with gfortran.
This is my conditional code:
if (angle < 90.0) then
print *, 'Angle is acute'
else if (angle < 180.0) then
print *, 'Angle is obtuse'
else
print *, 'Angle is reflex'
end if
This is my loop code:
integer :: i
do i=1,10,2
print *, i ! print odd numbers
end do
Both of them are completed with end statements, so I'm not sure what else it wants. I've only just started teaching myself today, so I'm still just copying codes verbatim from the tutorial and not sure how to troubleshoot anything.
In the tutorial you are following the pieces of code shown are not complete programs. They cannot be compiled as they are.
You will see this frequently, especially in answers on this site.
The code fragments shown miss a lot of context to make clear the parts that are to be taught. That's perhaps a little unfortunate, but Fortran is quite a verbose language, and so there's a trade-off for clarity.
For a complete program you've possibly seen that "all programs must have an end statement to complete them". You may think that the end if and end do statements are suitable for this. They are not: you need an end program statement. The following are two minimal programs:
end
and
end program
(There are also forms with a program statement.)
That is:
if (.true.) then
print *, "Hello, world!"
end if
end program
is compilable if and only if that last line exists.
Further, things like implicit none and variable declarations and definitions would be part of the implied context of example fragments.
If you are just learning and want to try code start with the following skeleton
program test
implicit none
<variable declarations>
<program code>
stop
contains
<function definitions>
end program
The above structure should be enough for most one use programs (write a program to do one thing). The stop above isn't required, it just makes it clear to see where the program instructions actually end.
If you want to use standard numeric types include the iso_fortran_env before the implicit none statement
program test
use, intrinsic :: iso_fortran_env
implicit none
the above will allow you to define integer(int32), integer(int64), real(real32), real(real64), etc.
I am programming a Fortran module, which is linked to external main program. I can only alter the subroutine. I have to detail a lot of data, but always the same. It takes too much time to do this on every call of the subroutine. How can I initialise the data only at the first call?
Currently, this is the subroutine:
subroutine sdvini(statev,coords,nstatv,ncrds,noel,npt,layer,kspt)
implicit none
integer imdat(100,100,50)
imdat(1,1,1:33)=(/1,8,13,24,48,72,111,148,156,165,182&
&,189,194,207,210,216,236,247,254,270,311,319,339,343,367,376&
&,393,397,421,438,447,473,492/)
.
. lots of data
.
do something
return
end
This setting of values on the first call to a procedure and retaining the values can be performed by explicit initialization. We often use the term initialization, as in this question, to mean an assignment as part of a setting up process. However, initialization means something more precise in Fortran terms.
An explicit initialization suitable for this question would be something like the very simple case
integer, save :: i=1 ! SAVE attribute would be implied, but made explicit
This is like having the assignment applied the first time the procedure is entered.
We can also use a data statement:
integer, save :: i
data i /1/
The SAVE attribute is what ensures that the value persists between entries to the procedure.
For arrays the idea is the same, perhaps using array constructors and reshape.
For very large arrays it is impractical to use data statements or initializers. Further, there are restrictions on what may appear in initializing a saved local variable. However, another idiom would be like
subroutine sub
logical, save :: firsttime=.TRUE.
integer, save :: obj(100,100,50)
if (firsttime) then
obj = ... ! Setting the value somehow, maybe even with a read
firsttime = .FALSE.
end if
end subroutine
NOTE: I'm still investigating this issue - please don't look into it yet - the mistake may be elsewhere
I would like an argument to a subroutine to be OPTIONAL, but that argument also happens to be an assume shape array. When I try to compile the module containing this subroutine, I get the following error:
PGF90-S-0189-Argument number 3 to (routine): association of scalar actual argument to array dummy argument (location)
The routine looks like this:
SUBROUTINE EXAMPLE(A, B, C)
IMPLICIT NONE
INTEGER, INTENT(IN) :: A, B
INTEGER, OPTIONAL, DIMENSION(:), INTENT(IN) :: C
INTEGER :: TEST
IF (PRESENT(C)) THEN
TEST=C(1)
PRINT *,TEST
ELSE
PRINT *,A,B
ENDIF
END SUBROUTINE EXAMPLE
It is contained within a module. I get the error when I try to call it with only two arguments from a subroutine which is USEing the module.
I have only found one possibly related question on the Portland Group forums here:
http://www.pgroup.com/userforum/viewtopic.php?t=624&sid=d76fdf8ca2bf4fc3109f4f49b1de0ad7
The answer boils down to the user using an optional argument which has not been allocated - I don't know if this applies in my case as I'm not using 'C' outside of the IF(PRESENT(C)) block, but could there be an implicit allocation going on when defining a variable as assumed shape, which cannot be carried out when it is not passed in the first place?
This problem is now resolved - you can indeed use assumed shape arrays as optional arguments. As pointed out in the comments - the error stemmed from an old version of a source file which was not being regenerated by a pre-processing step due to a bug. As a result, the call was not what I thought it was - it actually contained a single integer as the third argument.
Thanks for the help all.
I do not understand the behavior of the present() intrinsic function with pgf90 7.2. I wrote a 20 line sample program to test this, but the results still make no sense to me. Observe:
subroutine testopt(one,two,three,four,five)
implicit none
integer, intent(in) :: one,two
integer, intent(out) :: three
integer, intent(in), optional :: four
integer, intent(out), optional :: five
three = one + two
print *,"present check: ",present(four),present(five)
if (present(four) .and. present(five)) then
five = four*four
end if
end subroutine testopt
if I: call testopt(1,2,(any variable)) from my main program, it prints: "present check: T F". However if I: call testopt(1,2,(any variable)) from a subprogram it prints: "present check: T T". I expected to see "present check: F F" in either case, because I am only calling the subroutine with the 3 non-optional arguments, and neither of the optional ones. I cannot fathom why it would behave this way, and this is causing a major bug in a program I am working on. I appreciate any insight. Thanks.
Are you placing this subroutine in a module and then having a "use" statement for that module in the calling routine (main program or subroutine)? A typical rule is that many of the advanced / new features of Fortran 90 require an explicit interface so that both the caller and callee pass the arguments consistently. The easiest and best way to accomplish this is with module / use. Just a guess...
In Modern Fortran optional arguments must be declared as optional in the calling function (either through a module or an explicit interface). In Fortran 77 it was possible to simply leave out the last argument, if it was a scalar number, so optional arguments could be passed without extra declaration in the calling routine. This might not have been part of the Fortran standard, but it was a helpful feature provided by wise compiler implementations. Unfortunately, Modern Fortran killed this awesome feature.