Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

gFortran bug, or something else? 2

Status
Not open for further replies.

TwirlySocrates

Technical User
Nov 9, 2010
7
CA
Hi, I'm running numerical sediment chemistry models in FORTRAN.

I have a very bizarre problem:
I frequently debug my source code by using PRINT*, commands to write numbers to the console.
There's a couple of PRINT*, commands which, once removed from my source code, the program goes completely bonkers. Somehow, certain state variables are getting overwritten, throwing off the entire simulation.

In my mind, there's absolutely no reason that the presence or absence a PRINT*, command should alter my program's state variables ... right?

Would anyone have any idea what could cause this?
I'm using gFortran. Is it possible that the compiler is doing something strange?
 
I suggest to use the tool valgrind to detect a possible array out of bounds or a mismatch actual/dummy argument.

I also propose to activate all possible debug options like :

Code:
-g -fbounds-check -Wextra -ffpe-trap=invalid,zero,overflow

In a well written code without bug, inserting or deleting a print statement has no influence. But in a code containing bugs (i.e. the most usual situation), it is frequent to observe that the insertion of a write seems to delete a bug. And such a bug is difficult to locate because a small modification in the code changes its behavior and often suppresses the symptom.

François Jacq
 
I've had the same problem in the past. It always (and only) used to happen to me in fortran 77, never in F90, but anyway.

In all cases it appeared to be something with wrong array limits as FJacq already said.

You may also try to compile with the -Wall option, but possibly you won't save yourself of checking ALL array counters thoroughly, a tedious and painful job.

writing some counters and their maxima to the screen may reveal enough, if you're lucky
 
I've been using .F95 files, so I would assume the compiler is using fortran 95

Ok, thanks guys.

One last question:
What do all those options do?
 
-Wall means: Warn me in all possible warning cases that exist.
So, in case of -Woption1 -Woption2 etc.

I don't know about the other options, but I'm also going to try the options given by François
 

-g : to put debug information within the executable program to make the debugging easier (used by all debuggers like gdb, totalview or valgrind)

-fbounds-check : to activate the checking of array indexes to avoid out of bounds

-ffpe-trap : to stop in case of floating point exception

-Wall : to print out a lot of warnings during the compilation to point out possible troubles

-Wextra : still more messages not foreseen by -Wall

A remark about file suffix. It has usually nothing to do with the FORTRAN standard used in the file. It is only associated to the default format :
- free format with .f90 .f95
- fixed format with .f .for

In addition, under Unix, .F .FOR .F95 .F90 are associated to the use of the C pre-processor to interpret expression like #if #ifdef #include ...

François Jacq
 
A star for François :) He, just prevented that I had to read the manual
 
Thanks, this is extremely helpful.

What would be a good (preferably free) online reference for looking up the different standards?

I'd like to use fortran 95 standard, and so I'm using -std=f95.
I get a number of complaints from the compiler, but I don't always know the the proper syntax for f95 standard.

For example, it doesn't like when I use REAL*8 to define an 8-bit floating point variable.

Oh, and can ifort do f95? It doesn't seem to like .f95 file extensions.
 
The best address to get information about FORTRAN is the Wiki web site created by Jason Blevins :


You should find there all what you want.

I disagree with -std=f95 because most F95 compilers contain two very useful F2003 extensions :

-the generalization of the use of ALLOCATABLE arrays

-the standardization of the coupling C/FORTRAN

I call that F95+ !

About REAL*8, this is not standard because you cannot impose, on all the computers, real values having exactly 8 bytes. Even the notion of byte is not defined by the FORTRAN.

F90 has introduced the notion of "kind" :

Code:
integer,parameter :: dp=selected_real_kind(10,100)
real(dp)          :: value

With most compilers (but not all), you will get dp==8 because your have asked for a real value with a minimum of 10 significant digits (in base 10) and a minimum exponent range from -100 to 100.

DOUBLE PRECISION remains the standard double precision real value. It is possible to get the corresponding kind as follows :

Code:
integer,parameter :: standard_dp=kind(1.d0)
real(standard_dp) :: x(3)

The notation integer*4, real*8 ... have never been standard. But character*10 is OK even if the most common form is character(10).






François Jacq
 
How do you give that dp a global scope?

Or is that actually what I want to do?
I have a bunch of #include "bla.h" which would have REAL(dp), but I can't figure out where to put the corresponding
integer,parameter :: dp=selected_real_kind(15,307)
commands
 
Another thing - if I do this

REAL(dp) A,B
B = max(1.0,A)

I'm warned that the two arguments are of different types.
Should I worry about this?

Again, thank you for all your help.
That FORTRAN wiki is very helpful.
 
I'm warned that the two arguments are of different types.
Should I worry about this?

Yes you should !

It the compiler only issues a warning, then the code will probably run correctly. But this is not portable and another compiler could complain in issuing an error.

To correct the code, I suggest :

Code:
REAL(dp)  A,B
B = max(1.0_dp,A)



François Jacq
 
How do you give that dp a global scope?

I use a module for that which contains many constant values :

Code:
MODULE constants
  INTEGER,PARAMETER :: dp=selected_real_kind(15,100)
  REAL(dp)          :: avogadro  = 6.02252e23_dp     ! Avogadro number (1/mol)
  REAL(dp)          :: boltzmann = 1.38054e-23_dp    ! Boltzmann constant (J/K)
  REAL(dp)          :: gravity   = 9.80665_dp        ! earth gravity (m/s2)
  ...
END MODULE

In all other modules :

Code:
MODULE mymodule
  USE constants, ONLY : dp,gravity
  ...
END MODULE



François Jacq
 
I have some questions about Modules ...
I'm at my wits end - I have no idea what's wrong.

I have a module defined in a file timestepping.F90

MODULE timestepping
integer nstepmax, nwrite
integer nstepmax_sp, nwrite_sp
real*8 time, dt, dt_sp, dt_write, dt_sp_write
REAL*8 simStart, simEnd, spinYears
END MODULE timestepping

This .F90 file is listed in my makefile, and compiled (using gfortran) with everything else.

But when I try to access the module in another subroutine
(USE timestepping)
I get this:

In file code/numerics.F95:4

USE timestepping
1
Fatal Error: Can't open module file 'timestepping.mod' for reading at (1): No such file or directory

Did I do something wrong?
I've tried simple test cases where I try to set up a module in the same way, and they seem to work.
 
The error message is clear : the compiler does not find the file timestepping.mod which is normally generated during the compilation of "timestepping.F90".

Two possible reasons :
- the file timestepping.F90 has not been compiled yet
- the file timestepping.mod has been generated in a directory which is not accessible by the compiler

In both cases, you need to correct your makefile as follows :

Code:
bindir=bin
FFLAGS= -g -I $(bindir) -J $(bindir)

$(bindir)/timestepping.o $(bindir)/timestepping.mod : code/timestepping.F90
  gfortran -c $(FFLAGS) code/timestepping.F90

$(bindir)/numerics.o : code/numerics.F95 $(bindir)/timestepping.mod
  gfortran -c $(FFLAGS) code/numerics.F95

Explanations :

- the files bin/timestepping.obj and bin/timestepping.mod are the two targets of the compilation of code/timestepping.F90

- the file bin/timestepping.mod is a dependency for the compilation of code/numerics.F95

- the compilation flag -I allows you to precise the location of *.mod files needed when compiling a source file which USEs a particular module.

- the compilation flag -J allows you to precise where to generate *.mod files.




François Jacq
 

Correction : my makefile example was a little bit wrong because I forgot to precise the object files as main output of compilations

Code:
bindir=bin
FFLAGS= -g -I $(bindir) -J $(bindir)

$(bindir)/timestepping.o $(bindir)/timestepping.mod : code/timestepping.F90
  gfortran -c $(FFLAGS) -o $(bindir)/timestepping.o code/timestepping.F90

$(bindir)/numerics.o : code/numerics.F95 $(bindir)/timestepping.mod
  gfortran -c $(FFLAGS)  -o $(bindir)/numerics.o code/numerics.F95



François Jacq
 
Again, thanks for your help ...

I've done a simple test, and it doesn't seem to be working

I've done this
INTEGER,PARAMETER :: dp= selected_real_kind(15,100)
REAL(dp), PARAMETER :: pi = 3.1415926535897932384626

and later display the value:

WRITE(*,"(A, F15.10)") "Pi = ", pi

but it gives me this:
Pi = 3.1415927410

Also, is there a way of using a module to give access to a block of data, but still requiring that this data be passed as an argument to the module's subroutines?
 

You have made a mistake in your definition of pi. You should write :

Code:
      REAL(dp), PARAMETER :: pi = 3.1415926535897932384626_dp

In FORTRAN, when you write a=b, a and b may have different types. They are not related together ! The assignment = performs, if necessary, a conversion.

In your initial statement, 3.1415926535897932384626 is not a REAL(dp) value but a REAL value (equal to about 3.1415927). After that the assignment transforms this single precision real value into a REAL(dp) value but cannot restore magically the lost decimals.

François Jacq
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top