gfortran 4.9 Generic Type-Bound Operators - oop

I am trying to get generic type-bound operators to work using
gfortran 4.9, however I get errors. I have tried using Type(Vector)
and Class (Vector) without success.
Type :: Vector
Real :: x, y, z
Contains
Procedure :: set => vector_set
Procedure :: write => vector_write
generic :: Operator (+) => vector_add
End Type Vector
Function vector_add &
( &
u, v &
) &
Result (w)
!!$ Input
Type (Vector), Intent(in) :: u, v
!!$ Output
Type (Vector) :: w
w% x = u% x + v% x
w% y = u% y + v% y
w% z = u% z + v% z
End Function vector_add
I am getting the following error:
gfortran -o build/lib/foul.o -c -ffree-form -g -J./build/lib lib/foul.f
gfortran -o build/lib/vectors.o -c -ffree-form -g -J./build/lib lib/vectors.f
lib/vectors.f:194.28:
generic :: Operator (+) => vector_add
1
Error: Undefined specific binding 'vector_add' as target of GENERIC '+' at (1)
scons: *** [build/lib/vectors.o] Error 1
scons: building terminated because of errors.

Inserting the line
procedure :: vector_add
into the contains section of the type definition. As #IanH explains in his comment
Generic bindings resolve to specific bindings (analogous to how
generic procedures resolve to specific procedures). If you don't have
the line that you recommend inserting, then there is no specific
binding (listing a specific binding in the generic statement doesn't
define the specific binding - you need an explicit separate type bound
procedure statement to do that). The ordering isn't important.
I've promoted his explanation for ease of reading and to make this a better answer than my own now-expunged witchcraft-based explanation.

Related

Fortran READ into derived type not working with gfortran (Fortran runtime error: End of file)

I have a derived type in Fortran and I need to read values from a text file into that type. My problem is that my code is working fine with the Intel Fortran compiler as well as the NAG Fortran compiler, but GFortran exits with an error. The minimal working example is below.
Module my_mod
Type T
Real :: a
End Type T
Interface Read (Formatted)
Module Procedure read_T
End Interface
Contains
Subroutine read_T(var, unit, iotype, v_list, iostat, iomsg)
Class (T), Intent (Inout) :: var
Integer, Intent (In) :: unit
Character (*), Intent (In) :: iotype
Integer, Intent (In) :: v_list(:)
Integer, Intent (Out) :: iostat
Character (*), Intent (Inout) :: iomsg
Read (unit, *, iostat=iostat, iomsg=iomsg) var%a
End Subroutine
End Module my_mod
Program main
Use my_mod
Implicit None
Type(T) :: x
Type(T) :: y
Open(unit=20, file='data.txt', action='read')
Read(20, *) x ! Here GFortran fails because it somehow reaches EOF
Write(*, *) x
Read(20, *) y
Write(*, *) y
End Program main
with the data.txt file:
1.0
2.0
With GFortran I get the error
At line 30 of file test.f90 (unit = 20, file = 'data.txt')
Fortran runtime error: End of file
Error termination. Backtrace:
#0 0x7f27a76fef2f in finalize_transfer
at ../.././libgfortran/io/transfer.c:4175
#1 0x400aca in ???
#2 0x400b86 in ???
#3 0x7f27a69a8504 in ???
#4 0x4007e8 in ???
#5 0xffffffffffffffff in ???
One thing that works is to replace the Read statements as follows
Read(20, fmt='(DT)', advance='no') x ! Works with all compilers :)
Write(*, *) x
Read(20, fmt='(DT)', advance='no') y ! Works with all compilers :)
Write(*, *) y
So my question .. is it possible to get the same behaviour in GFortran without fmt='(DT)', advance='no'?
And who has the correct behavior? GFortran or Intel Fortran and NAG Fortran?
Thanks for any help,
Simon

Fortran Mismatch in components of derived type

I am currently developing a software in Fortran. It has been already a couple of times I've encountered the error below. Previously I just managed to undo those changes and rewrite the code again as I was not able to understand the issue.
Obviously, the issue came back again. So I am wondering why it happens. What am I doing in the code thats triggering it.
The compiler used is gfortran-9. I also tried to compile in gfortran-10 (ubuntu 20.04) with the hope it was a compiler bug already solved :/. The error shown is the same but with different elements.
This part of the software consists in a library (modules starting with SIO_...) which is using another one (modules starting with SHR_...).
Project structure:
soulio (library folder)
src
tests/unit
soulshared (external library)
The file triggering the error at compilation times is soulio/tests/unit/ncSpatialFile.F90. It has the following imports:
module ncSpatialFile_test
use netcdf
use SHR_file_mod, only: removeIfExists
use SHR_testSuite_mod, only: testSuite
use SHR_datetime_mod, only: datetime, timedelta, clock
use SIO_ncSpatialFile_mod, only: ncSpatialFile_abs <- gfortran-9 complains about this line
...
Imports from soulio/src/ncSpatialFile_abs.F90
module SIO_ncSpatialFile_abs
! use netcdf
use SHR_datetime_mod, only: clock, datetime, timedelta
use SHR_strings_mod, only: string
use SHR_precision_mod, only: sp
use SHR_array_mod, only: initArrayRange
use SHR_error_mod, only: raiseError
use SIO_ncfile_mod, only: ncfile
use SIO_ncDimensions_mod, only: ncDimensions
use SIO_ncVariables_mod, only: ncVariables
use SIO_grid_mod, only: grid
use SIO_parallel_mod, only: mpiContext_type
use SIO_ncSlimSpatialDims_mod, only: ncSlimSpatialDims
use SIO_ncFullSpatialDims_mod, only: ncFullSpatialDims
use SIO_ncSpatialDims_abs, only: ncSpatialDims
use SIO_ncParams_mod, only: NC_TIME_DIM_NAME, NC_SPATIAL_DIM_NAME!, SIO_NC_GLOBAL_ATTR
use SIO_ncOtherDim_mod, only: ncOtherDim
use SIO_ncTimeDim_mod, only: ncTimeDim
use SIO_ncVar_mod, only: ncVar
use SIO_ncDim_mod, only: ncDim, ncDimHolder
use SIO_ncTime_mod, only: ncTime
use SIO_ncDimensionsRequest_mod, only: ncDimensionsRequest
use SIO_ncVariableBounds_mod, only: ncVariableBounds
use SIO_ncAttributes_mod, only: ncAttributes
... (too many imports?)
type, abstract :: ncSpatialFile_abs
! netcdf file interface
class(ncfile), allocatable :: ncfile
! time series
class(clock), allocatable :: ncClock
soulio/soulshared/src/datetime_mod.F90
module SHR_datetime_mod
use iso_fortran_env, only: real32, real64
use iso_c_binding, only: c_char, c_int, c_null_char
use SHR_error_mod, only: raiseError
implicit none
private
public :: datetime, timedelta, clock, calendar
...
Error in gfortran-10:
soulio/tests/unit/ncSpatialFile_test.F90:20:7:
20 | use SIO_ncSpatialFile_mod, only: ncSpatialFile_abs
| 1
Fatal Error: Mismatch in components of derived type ‘__vtype_shr_datetime_mod_Calendar’ from ‘shr_datetime_mod’ at (1): expecting ‘calendar_assign’, but got ‘getdaysinmonth’
compilation terminated.
make[2]: *** [tests/unit/CMakeFiles/soulio_test.dir/build.make:232: tests/unit/CMakeFiles/soulio_test.dir/ncSpatialFile_test.F90.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:260: tests/unit/CMakeFiles/soulio_test.dir/all] Error 2
Error in gfortran-9:
soulio/tests/unit/ncSpatialFile_test.F90:20:6:
20 | use SIO_ncSpatialFile_mod, only: ncSpatialFile_abs
| 1
Fatal Error: Mismatch in components of derived type ‘__vtype_shr_datetime_mod_Clock’ from ‘shr_datetime_mod’ at (1): expecting ‘currenttickintervals’, but got ‘clock_assign’
compilation terminated.
make[2]: *** [tests/unit/CMakeFiles/soulio_test.dir/build.make:232: tests/unit/CMakeFiles/soulio_test.dir/ncSpatialFile_test.F90.o] Error 1
The error came up after modifing ncSpatialFile_test but not datetime.
I find the error confusing. Any ideas about what the compiler is trying to say? Any other advice in how to dig further?
Edit:
Datetime_mod file is taken from https://github.com/wavebitscientific/datetime-fortran. There are a few modifications but its the same structure.
clock declaration:
type :: clock
type(datetime) :: startTime
type(datetime) :: stopTime
type(datetime) :: currentTime
type(datetime) :: prevTime !> currentTime - 1 timestep
type(datetime) :: nextTime !> currentTime + 1 timestep
type(timedelta) :: tickInterval
logical :: alarm = .false.
logical :: started = .false.
logical :: stopped = .false.
logical :: nullified = .false. !< it is considered not defined
contains
procedure :: getStartTime
procedure :: getStopTime
procedure :: reset
procedure :: tick
procedure :: toString => toString_clock
procedure :: isStopped
procedure :: isNull
! true when the condition is satisfied for the current time step
procedure :: isBeginYear, isEndYear
procedure :: isBeginMonth, isEndMonth
procedure :: isBeginDay, isEndDay
procedure :: isBeginClock, isEndClock
procedure :: getTickIntervals
procedure :: totalTickIntervals
procedure :: currentTickIntervals
!
procedure, private :: clock_assign
procedure, private, pass(from) :: clock_assign_tickInterval
generic :: assignment(=) => clock_assign, clock_assign_tickInterval
procedure :: findEquivalentCurrentTime
procedure :: getCalendarType => getCalendarType_clock
procedure, private :: equiv_clock
generic :: operator(==) => equiv_clock
procedure :: isInAbsoluteBounds
end type clock
As suggested by #veryreverie in the comments section, it was a problem of cache.
The cmake project places its mod files into tree project/lib. Those files are not removed when I clean the build folder. Because of this, some inconsistencies were happening.

Get warning about unused identifiers from use only

Let's say I have the following code:
module test_mod
implicit none
private
public :: A, B, double
integer :: A, C
integer, parameter :: B = 2
contains
integer elemental function double(n)
integer, intent(in) :: n
double = 2 * n
end function
end module
program test_prog
use test_mod, only: A, B, double
implicit none
A = 3
write(*, *) A
end program
If I compile with gfortran -Wall -Wextra I correctly get warnings about:
Unused variable C in test_mod.
Imported but unused variable B in the program.
But I would like to also get a warning about the fact that double is imported, but unused.
Is there a compiler option that I overlook? Is there a compiler that does this?
Is it coming in later versions of gfortran? (I used 8.2.1)

using Fortran Module from external files

I would like to call subroutines contained in a module. the module is saved in a separate file with my_mod.f95 filename.
module calc_mean
! this module contains two subroutines
implicit none
public :: calc_sum
public :: mean
contains
subroutine calc_sum(x,n,s)
! this subroutine calculates sum of elements of a vector
! x the vector
! n size of the vector
! s sum of elements of x
integer, intent(in):: n
real, intent(in):: x(n)
integer :: i
real, intent(out):: s
s=0
do i=1,n
s=s+x(i)
end do
end subroutine calc_sum
!
!
!
subroutine mean(x,n,xav)
! this subroutine calculates the mean of a vector
! x the vector
! n size of the vector
! xav mean of x
integer, intent(in):: n
real, intent(in):: x(n)
real, intent(out):: xav
real :: s
!
!
call calc_sum(x,n,s)
xav=s/n
end subroutine mean
end module calc_mean
I have the main program saved in a different file with 'my_program.f95'
program find_mean
! this program calculates mean of a vector
use calc_mean
implicit none
! read the vector from a file
integer, parameter ::n=200
integer :: un, ierror
character (len=25):: filename
real :: x(n), xav
un=30
filename='randn.txt'
!
OPEN (UNIT=un, FILE=filename, STATUS='OLD', ACTION='READ', IOSTAT=ierror)
read(un,*) x !
!
call mean(x,n,xav)
write (*,100) xav
100 format ('mean of x is', f15.8)
end program find_mean
when I compile the main program with geany, I got the following error message. Please, help me!
**
/usr/bin/ld: /tmp/cctnlPMO.o: in function MAIN__': my_program.f08:(.text+0x1e1): undefined reference to __calc_mean_MOD_mean'
collect2: error: ld returned 1 exit status
**
When I save both the main program and the module to the same file and run it, everything is fine.

gfortran, DLL and nothing making sense (or working) at all [duplicate]

This question already has answers here:
Fortran functions returning unexpected types and values
(3 answers)
Closed 2 years ago.
I have the following short piece of code in Fortran, which I named myDLL.f90:
Real(Kind=8) Function mySinCos(x,y)
Real(Kind=8), Intent(In) :: x, y
mySinCos = Sin(x)*Cos(y)
End Function mySinCos
Real(Kind=8) Function myPiSinCos(x,y)
Real(Kind=8), Intent(In) :: x, y
Real(Kind=8), Parameter :: Pi = 4.0d0*Datan(1.0d0)
myPiSinCos = Sin(Pi*x)*Cos(Pi*y)
End Function myPiSinCos
And the following main program TestDLL.f90:
Program TestDLL
Real(Kind=8) :: x, y
Real(Kind=8) :: a, b
x = 2.0d-01
y = 9.0d-01
a = mySinCos(x,y) !Should be 0.12349483641187213
b = myPiSinCos(x,y) !Should be -0.5590169943749475
Write(*,*) a
Write(*,*) b
End Program TestDLL
I compiled and linked the above sources with:
gfortran -shared -fPIC -o myDLL.dll myDLL.f90
gfortran -o a.exe TestDLL.f90 -L. myDLL.dll
No compilation/linkedition errors and a.exe runs without error messages. What it produces is:
6.0000000000000000
6.0000000000000000
Which obviously aren't the expected results as sin(...)*cos(...) must never be > 0.5 (or < -0.5), let alone 6.0000[...].
In a nutshell: compiled well, linked well, executed well and produced garbage.
Changing either x or y doesn't change the results. They're always 6.0000[...].
What went wrong? The example above doesn't differ a lot from other simple examples I've found in the internet.
I'm using GNU Fortran (MinGW.org GCC Build-20200227-1) 9.2.0, Windows 10 64-bit.
It works fine if I turn the two functions into a module:
Module myDLL
Implicit None
Contains
... The two original functions are inserted here ...
End Module myDLL
and import/use the module in the main program:
Program TestDLL
Use myDLL
Implicit None
... Other commands are inserted here ...
End Program TestDLL
Then, and only then, the correct results are spit.