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

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

Related

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.

gfortran 4.9 Generic Type-Bound Operators

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.

Fortran, Finalization at (1) is not yet implemented

I am trying to implement a simple finalizer, but I can't get even this example to compile:
MODULE m
TYPE :: t1
REAL a,b
END TYPE
TYPE, EXTENDS(t1) :: t2
REAL,POINTER :: c(:),d(:)
CONTAINS
FINAL :: t2f
END TYPE
TYPE, EXTENDS(t2) :: t3
REAL,POINTER :: e
CONTAINS
FINAL :: t3f
END TYPE
CONTAINS
SUBROUTINE t2f(x) ! Finalizer for TYPE(t2)'s extra components
TYPE(t2) :: x
print *, 'entering t2f'
IF (ASSOCIATED(x%c)) then
print *, ' c allocated, cleaning up'
DEALLOCATE(x%c)
end if
IF (ASSOCIATED(x%d)) then
print *, ' d allocated, cleaning up'
DEALLOCATE(x%d)
end if
END SUBROUTINE
SUBROUTINE t3f(y) ! Finalizer for TYPE(t3)'s extra components
TYPE(t3) :: y
print *, 'entering t3f'
IF (ASSOCIATED(y%e)) then
print *, ' e allocated, cleanup up'
DEALLOCATE(y%e)
end if
END SUBROUTINE
END MODULE
using GNU Fortran (GCC) 4.8.2 20131212 (Red Hat 4.8.2-7) gives me this error output:
$ gfortran -c
m_example.f03 m_example.f03:5.26:
TYPE, EXTENDS(t1) :: t2
1 Error: Finalization at (1) is not yet implemented m_example.f03:10.26:
TYPE, EXTENDS(t2) :: t3
1 Error: Finalization at (1) is not yet implemented
Is this a bug, does it mean that finalizers are not yet implemented in gfortran, or am I doing something wrong?
Since gcc 4.9, finalizers are recognized. Furthermore, if you do not implement them yourself, the compiler appears to generate finalization code itself.
Which unfortunately leads to bug 59765. Still available in gcc gfortran 4.10, as I was unfortunate to discover.

Binary Read/Write of Data Types with Allocatable Components in Fortran90+

What is the best way to save a binary snapshot of the variable save which is made out of sample data type below?
program save_it
type core
integer, dimension(8) :: indx
end type core
type sample
integer :: a
real*8, dimension(:), allocatable :: b
type(core), dimension(:), allocatable :: c
end type sample
! here it comes
type(sample) :: save
! here we allocate all componenets of variable "save"
!.
!.
! Now, how to write/read variable "save" to/from external file?
end program save_it
There is pretty straight binary input/output streaming in C++ but I don't know how to do it in Fortran 90+.
If by Fortran90+ you mean you are happy with Fortran 2003, then there is the option of user-defined derived type IO. This allows you to wrap the extra bookkeeping required for the allocation in the write statement. I'll put example code at the bottom.
If you don't want to use this feature, which is possibly because you don't have a compiler which supports it (I've tested with ifort 14), then you can mimic the bookkeeping easily enough.
The crucial part is just sending out and reading back in the sizes and allocating the variables before the read.
The code:
module types
type core
integer, dimension(8) :: indx
end type core
type sample
integer :: a
real*8, dimension(:), allocatable :: b
type(core), dimension(:), allocatable :: c
contains
procedure write_sample
procedure read_sample
generic :: write(unformatted) => write_sample
generic :: read(unformatted) => read_sample
end type sample
contains
! Unformatted writing for the sample derived type
subroutine write_sample(dtv, unit, iostat, iomsg)
class(sample), intent(in) :: dtv
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
integer i
! Write a record giving sizes for the allocation
write(unit, iostat=iostat, iomsg=iomsg) SIZE(dtv%b), SIZE(dtv%c)
write(unit, iostat=iostat, iomsg=iomsg) dtv%a, dtv%b, &
(dtv%c(i)%indx, i=1,SIZE(dtv%c))
end subroutine write_sample
! Unformatted reading for the sample derived type
subroutine read_sample(dtv, unit, iostat, iomsg)
class(sample), intent(inout) :: dtv
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
integer i
integer sizeb, sizec
! We first have a record telling us the sizes of components
read(unit, iostat=iostat, iomsg=iomsg) sizeb, sizec
! So we do the allocation
allocate(dtv%b(sizeb), dtv%c(sizec))
! And then finally the reading.
read(unit, iostat=iostat, iomsg=iomsg) dtv%a, dtv%b, &
(dtv%c(i)%indx, i=1,SIZE(dtv%c))
end subroutine read_sample
end module types
program save_it
use types
implicit none
integer i, unit_in, unit_out
! here it comes
type(sample) :: save
type(sample) :: save_test
! Define some values - using ifort don't forget to set the compile flag
save%a = 14
save%b = [(i*1., i=1, 10)]
save%c = [core([(i, i=1,8)]), core([(i, i=11, 18)])]
! Write out the derived type
open(newunit=unit_out, file='serial', form='unformatted', &
status='replace', action='write')
write(unit_out) save
close(unit_out)
! Read in the derived type to a new one
open(newunit=unit_in, file='serial', form='unformatted', &
status='old', action='read')
read(unit_in) save_test
close(unit_in)
! Test, if we want to be certain
end program save_it
There's certainly a lot of work to be done on making it robust.