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.
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 have multiple errors with this fortran code
tried many times to correct them but no clue
i hope someone can figure it out
Program mr
implicit none
logical::p,q,fun
read(*,*)p,q
print*,"------"
print*,"|p|q|p->q"
print*,"------"
print*,"|true|true|",function(true,true),"|"
print*,"------"
print,"|true|false|",fun(true,false),"|"
print*,"------"
print,"|false|true|",fun(false,true),"|"
print*,"------"
print,"|false|false|",fun(false,false),"|"
print*,"------"
end program mr
logical function fun(p,q)
logical::p,q
if(p==true .and. q==false)then
fun=false
else
fun=true
end if
end function
As mentioned in the comments, there is nothing special about the variable true and false. They do not have pre-defined types or values. This misunderstanding is the cause of the error messages: the compiler says Symbol 'true' does not have an implicit type. (The implicit none statement at the beginning is good here, as it prevents you from other less-helpful errors.)
The defined logical parameters are instead .true. and .false.. Note the periods on either side. You should replace each instance of true with .true. and each instance of false with .false. After that, the compiler points out a few other errors for me:
Missing a few * after print
Switch == to .eqv. for comparing logicals
Change function to fun in main body
There are some other improvements to make: put subroutines in a module, cleanup the logic in fun, and indent the code. But this should be enough to get you started. I am deliberately not pasting the final code here so you can make the changes yourself - good luck!
Is a plain RETURN statement (without any arguments) just before END SUBROUTINE in large legacy codes a good practice or should we just remove it?
The code I am working with is a big legacy code (for scientific computing) where parts of the code were originally written with Fortran 77, while majority new development is in Fortran 95 and above. There is some interspersed C code an Python scripting as well.
The Intel developer guide clearly mentions that End Subroutine already initiates Return:
https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-end
On the other hand, I remember having been taught in 2000s that it is always good practice to specify an explicit RETURN statement before END SUBROUTINE.
Typical subroutine structure is mentioned as follows (e.g., Chapman's Fortran for Scientists and Engineers, 4th Edition):
SUBROUTINE subroutine_name ( argument_list )
...
(Declaration section)
...
(Execution section)
...
RETURN
END SUBROUTINE [subroutine_name]
If Return statement (without any arguments) is not a good practice then why even mention it as part of the structure, especially outside the "Execution section"? CYCLE or EXIT etc. are never mentioned as part of a standard Subroutine structure. So, why the RETURN?
As the Intel guide mentions, it's pointless since the "end subroutine" statement already handles it. Return is useful if you need to, say, return inside a loop or such (but then there's a school of thought saying you should structure your control flow such that you never return in the middle of a loop. YMMV).
It is a noise. A useless statement that only distracts from the useful code. Inexperienced people may wonder why it is there.
It is similar to putting a STOP right before the END PROGRAM. That one is even worse, because it has some side-effects that can confuse inexperienced programmers and users of the program.
Some very old Fortran version (the first 66 standard) may have required it, but that is computing prehistory.
I'm learning Fortran for a new job and started writing some very, very basic programs. To compile, I'm using gcc version 4.6.2, and I'm working on Linux Suse OS (if that matters at all). I believe the version of Fortran I'm using is F90 or F95. The code is written using the VIM text editor.
Here is the program I've written
INTEGER, PARAMETER :: x = 2, y = 3
INTEGER :: z = x+y
print *, z
That's it! Oh, and the lines are indented, They start on column 8, so indentation isn't an issue.
UPDATE 1
I have tried doing this like so:
PROGRAM print_stuff
print *, z
END PROGRAM print_stuff
I also tried adding the IMPLICIT NONE statement to all of that and didn't get a change in the error.
END UPDATE 1
I save, quit, and compile. The compiler returns this error:
Error: Unexpected end of file in 'practice1.f'
Anyone know what the problem is? I've even tried removing the print statement and just having the variable declarations but the same error occurs. It's keeping me from practicing Fortran at all!
Your first version
INTEGER, PARAMETER :: x = 2, y = 3
INTEGER :: z = x+y
print *, z
is NOT a valid Fortran program. Every valid program ends with the end statement. A 'program' without an end statement is not syntactically correct. Keep reading your introductory tutorial.
I suggest you get into the habit of starting your programs with a program statement, with a name, such as
program myprog
and ending them with
end program myprog
Strictly, neither the program statement nor a program name is necessary but they do make things look a bit more comprehensible.
Oh, and while I'm writing ... don't get into the habit of starting lines at column 8, that smacks of the now out-dated fixed-form source. If you are using a reasonable compiler (such as gcc) give your filenames the .f90 suffix and let your source code run free. All the while observing good habits of indentation of course.
EDIT in response to OP's edits
PROGRAM print_stuff
print *, z
END PROGRAM print_stuff
and
INTEGER, PARAMETER :: x = 2, y = 3
INTEGER :: z = x+y
print *, z
END
are both syntactically correct. Both gfortran (v4.1.2) and Intel Fortran (v13.0.1) compile both correctly and produce executables which execute.
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".