Related
When I run this program using gfortran test.f95, it shows an error
At line 10 of file test.f95 (unit = 15, file = 'open.dat')
Fortran runtime error: End of file
Can someone tell me what is wrong here?
implicit none
integer:: a,b,c,ios
open(unit=15,file="open.dat",status='unknown', action='readwrite',iostat=ios)
open(unit=16,file="open.out",status="unknown",action='write')
do a=1,100
write(15,*)a
end do
do c=1,45,1
read(15,*)
read(15,*)b
write(16,*)b
end do
stop
end
Make sure to change location in the file with rewind/fseek
implicit none
integer :: a, b, c, ios, ierr
open( unit=15, file="open.dat", action='readwrite', iostat=ios)
open( unit=16, file="open.out", action='write')
do a=1,100
write(15,*)a
end do
! Here we need to get back to beginning of file
! otherwise, you try to read where you finished writing
! at the end of file
! CALL FSEEK(UNIT, OFFSET, WHENCE[, STATUS])
! https://gcc.gnu.org/onlinedocs/gfortran/FSEEK.html
! call fseek(15, 0, 0, ierr)
! you can also use rewind file
! https://www.fortran.com/F77_std/rjcnf0001-sh-12.html
rewind(15)
do c=1,45,1
read(15,*)
read(15,*)b
write(16,*)b
end do
end
Context: I have the intention to put a certain Fortran subroutine to some tests to see what is wrong with it. It's a numerical simulation and the results are not matching with theory. I use the write statement to do some simple debugging.
The problem: While a file is open in my main routine, I can't seem to write anything to the screen (so I can't check which stuff are being incorrectly passed to a certain chain of subroutines and etc.). It writes all fine when I do it before opening the file, but not inside it (after opening and after closing it).
Here is the code I'm referring to:
WRITE(*,*) 'BLA !<---------------------------------------
WRITE(*,*) 'BLA BLA' !<---------------------------------------
do p=1,N !open files
write(posvel, "(a,i0,a)") "1Dposveldatacomelasticaxy1", p, ".dat"
OPEN(unit=p, file=trim(posvel), status="unknown")
end do
WRITE(*,*) 'bla' !<---------------------------------------
t = tmin
cont = 0
do while ((t + dt) < (tmax))
t = t+dt
cont = cont+1
do i = 1, N
forcax(i) = 0.0d0
forcay(i) = flagy(i)*gravidade(m(i))
do j = 1, N
call coefficients(m(i), m(j), gama_n, k_n)
Fx_elastica(j,i) = 0.0d0
Fy_elastica(j,i) = 0.0d0
Fx_viscosa(j,i) = 0.0d0
Fy_viscosa(j,i) = 0.0d0
WRITE(*,*) 'inside j loop' !<---------------------------------------
if (i .NE. j) then
if ( (abs(sqrt(((xold(i)-xold(j))**2)+(yold(i)-yold(j))**2))).LE. (a(i)+a(j)) ) then
WRITE(*,*) 'inside collision' !<---------------------------------------
call forca_elastica(k_n, a(i), a(j), xold(i), xold(j), yold(i), yold(j), Fx_elastica(j,i),&
Fy_elastica(j,i))
if (Fx_elastica(j,i) .GT. 0.0d0) then
Fx_elastica(i,j) = -Fx_elastica(j,i)
WRITE(*,*) 'elastic x is being passed' !<---------------------------------------
end if
if (Fy_elastica(j,i) .GT. 0.0d0) then
Fy_elastica(i,j) = -Fy_elastica(j,i)
WRITE(*,*) 'elastic y is being passed' !<---------------------------------------
end if
forcax(i) = forcax(i) + flagex(i)*Fx_elastica(j,i)
forcay(i) = forcay(i) + flagey(i)*Fy_elastica(j,i)
end do
call integracao_Euler_xy (xold(i),xnew(i),vxold(i),vxnew(i),forcax(i),yold(i),ynew(i),vyold(i),vynew(i),forcay(i),m(i))
if (mod (cont,5000).eq. 0) then
WRITE(p, *) int(cont/5000), t, xold(i), yold(i), forcax(i), forcay(i) !<---------------------------------------
end if
end do
end do
do p = 1,N !close files
close(unit=p)
end do
Just look at the WRITE statements. The first two appear on the screen alright. After OPENing the files, though... It doesn't. The WRITE statements that depend on conditions are the ones I want to see, but Fortran is not even writing the ones that don't depend on those conditions. Also, take a look at the last WRITE statement - it writes to the file with no problems.
Any ideas on how to fix/contour this problem?
I'm using Fortran 90.
You should not use small numbers for unit numbers. You are looping from 1 with a step of 1. You are almost guaranteed to hit the pre-connected units for standard output and standard input. See also Standard input and output units in Fortran 90?
Loop from some larger number, say from 100, or use newunit= and store the unit numbers in some array.
Also note that p has value N+1 at WRITE(p, *) ....
I am in the process of learning how to use OpenMPI and Fortran. By making use of the OpenMPI documentation, I have tried to create a simple client/server program. However, when I run it I get the following error from the client:
[Laptop:13402] [[54220,1],0] ORTE_ERROR_LOG: Not found in file dpm_orte.c at line 167
[Laptop:13402] *** An error occurred in MPI_Comm_connect
[Laptop:13402] *** reported by process [3553361921,0]
[Laptop:13402] *** on communicator MPI_COMM_WORLD
[Laptop:13402] *** MPI_ERR_INTERN: internal error
[Laptop:13402] *** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort,
[Laptop:13402] *** and potentially your MPI job)
-------------------------------------------------------
Primary job terminated normally, but 1 process returned
a non-zero exit code.. Per user-direction, the job has been aborted.
-------------------------------------------------------
--------------------------------------------------------------------------
mpiexec detected that one or more processes exited with non-zero status, thus causing
the job to be terminated. The first process to do so was:
Process name: [[54220,1],0]
Exit code: 17
--------------------------------------------------------------------------
The code for the Server and Client can be seen below:
server.f90
program name
use mpi
implicit none
! type declaration statements
INTEGER :: ierr, size, newcomm, loop, buf(255), status(MPI_STATUS_SIZE)
CHARACTER(MPI_MAX_PORT_NAME) :: port_name
! executable statements
call MPI_Init(ierr)
call MPI_Comm_size(MPI_COMM_WORLD, size, ierr)
call MPI_Open_port(MPI_INFO_NULL, port_name, ierr)
print *, "Port name is: ", port_name
do while (.true.)
call MPI_Comm_accept(port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, newcomm, ierr)
loop = 1
do while (loop .eq. 1)
call MPI_Recv(buf, 255, MPI_INTEGER, MPI_ANY_SOURCE, MPI_ANY_TAG, newcomm, status, ierr)
print *, "Looping the loop."
loop = 0
enddo
call MPI_Comm_free(newcomm, ierr)
call MPI_Close_port(port_name, ierr)
call MPI_Finalize(ierr)
enddo
end program name
client.f90
program name
use mpi
implicit none
! type declaration statements
INTEGER :: ierr, buf(255), tag, newcomm
CHARACTER(MPI_MAX_PORT_NAME) :: port_name
LOGICAL :: done
! executable statements
call MPI_Init(ierr)
print *, "Please provide me with the port name: "
read(*,*) port_name
call MPI_Comm_connect(port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, newcomm, ierr)
done = .false.
do while (.not. done)
tag = 0
call MPI_Send(buf, 255, MPI_INTEGER, 0, tag, newcomm, ierr)
done = .true.
enddo
call MPI_Send(buf, 0, MPI_INTEGER, 0, 1, newcomm, ierr)
call MPI_Comm_Disconnect(newcomm, ierr)
call MPI_Finalize(ierr)
end program name
I use mpif90 server.f90 -o server.out and mpif90 client.f90 -o client.out to compile and mpiexec -np 1 server.out and mpiexec -np 1 client.out to run the programs. It is when providing the client with the port name (i.e. when I press enter after the read) that the error occurs.
which dpm_orte.c returns dpm_orte.c not found
I am running Linux and I installed OpenMPI 1.10.3-1 from the Arch Extra.
It's a trivial Fortran input handling mistake and has nothing really to do with MPI (besides the error message that Open MPI outputs being completely incomprehensible). Just insert a line in client.f90 to print the value of port_name right after reading it:
print *, "Please provide me with the port name: "
read(*,*) port_name
print *, port_name
With the actual port name being something like 2527592448.0;tcp://10.0.1.6,10.0.1.2,192.168.122.1,10.10.11.10:55837+2527592449.0;tcp://10.0.1.6,10.0.1.4,192.168.122.1,10.10.11.10::300 the output will be 2527592448.0. The list directed input treats ; as separator and stops reading after it, thus the port address passed to MPI_COMM_CONNECT is incomplete.
The solution is to replace read(*,*) port_name with
read(*,'(A)') port_name
Also, the loop in the server is badly written. You cannot call MPI_FINALIZE more than once. And closing the port is also a bad idea given that you are calling MPI_COMM_ACCEPT immediately after. The correct loop would be:
! executable statements
call MPI_Init(ierr)
call MPI_Comm_size(MPI_COMM_WORLD, size, ierr)
call MPI_Open_port(MPI_INFO_NULL, port_name, ierr)
print *, "Port name is: ", port_name
do while (.true.)
call MPI_Comm_accept(port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, newcomm, ierr)
loop = 1
do while (loop .eq. 1)
call MPI_Recv(buf, 255, MPI_INTEGER, MPI_ANY_SOURCE, MPI_ANY_TAG, newcomm, status, ierr)
print *, "Looping the loop."
loop = 0
enddo
call MPI_Comm_disconnect(newcomm, ierr)
call MPI_Comm_free(newcomm, ierr)
enddo
call MPI_Close_port(port_name, ierr)
call MPI_Finalize(ierr)
I am trying to compile this following code in gfortran compiler:
do_cmd = .not. is_group
do while (.not. EOF(unit=100) .and. .not. flag_stop)
read (100, '(A)', iostat = ios) buf
if (buf(1:1)=="#") then
! comment line
elseif ((buf(1:2)=="v ") .and. do_cmd) then ! vertex
read(buf(2:), *, iostat=ios) p(1), p(2), p(3)
if (ios.ne.0) then
print "(/,2x,'Error of reading vertex position from obj-file (line #'(I3)');')", line_index
stop
end if
But I get these errors when the code is compiling:
do while (.not. EOF(unit=100) .and. .not. flag_stop)
1
Error: Keyword argument requires explicit interface for procedure ‘eof’ at (1)
and;
do while (.not. EOF(unit=100) .and. .not. flag_stop)
1
Error: Function ‘eof’ at (1) has no IMPLICIT type
I will be so grateful if anyone could help me.
edit:
I'm very new in fortran and couldn't find out how eof function works in gfortran.
What does it mean using unit=100 in argument?
And also Thought it is a logical function by default. How should I implicit its type?
As far as I know, EOF is not part of the Fortran Standard. At least I can't find it anywhere.
In most programming languages, EOF stands for "End of File", and it is fairly obvious to me that the EOF in your example is supposed to be a logical function that returns .TRUE. if and only if the read pointer associated with unit (in your case 100) points to the end of the file.
You can use the ios variable to check whether an EOF was encountered during the read. In that case, it will be -1. You can then use the exit statement to immediately quit the loop.
If you don't like the -1, and you use a Fortran 2003 compatible compiler, you might even use the module ISO_FORTRAN_ENV, which provides (amongst other things) the parameter IOSTAT_END.
Here's a very simple example:
program iso
use ISO_FORTRAN_ENV
implicit none
integer, parameter :: u = 100
character(len=80) :: buf
integer :: ios
open(unit=u, action='READ', status='OLD', file='data.dat')
read_loop : do
read(u, '(A)', iostat=ios) buf
if (ios == IOSTAT_END) exit read_loop ! EOF
if (buf(1:1) == '#') cycle read_loop ! This line is a comment
write(*, *) buf
end do read_loop
close(u)
end program iso
One note though: This code is meant as an example. It only exits the loop if it encounters an EOF -- not if the read fails for any other reason. (There are some other reasons that the the read would fail.) If that other error is persistent, then this will lead to an infinite loop.
It may be useful to try a user-defined EOF function (as shown below) to minimize the amount of code modifications; but because this function is rather inefficient, I guess it is probably better to rewrite the original code so as to utilize iostat in read statements directly (as suggested above)...
module eofmod !<-- please save this in a separate file, compile, and link with other programs
implicit none
contains
logical function EOF( unit )
integer, optional :: unit
integer :: ios
if ( .not. present( unit ) ) stop "no unit given"
read( unit, *, iostat=ios )
if ( ios == -1 ) then
EOF = .true.
else
EOF = .false. ; backspace( unit )
endif
end function
end module
program test
use eofmod !<-- needs to be inserted at the top of routines (or modules) where "EOF" is used
implicit none
character(200) :: buf
open(10, file="test.dat", status="old")
do while ( .not. EOF( unit=10 ) )
read( 10, "(a)" ) buf
print "(a)", trim( buf )
enddo
close(10)
end program
I'm try to compile a Fortran application to write HDF5 files. My compiler is gfortran 4.7.2. Specifically, I'm trying to create a dataspace with a certain set of current dimensions and maximum dimensions. I want the last dimension to have an unlimited maximum dimension. There isn't much documentation for Fortran HDF5, but I was able to figure out that this can be specified by setting that dimension in question to H5S_UNLIMITED_F. This value is supposed to evaluate to -1, but in my application it instead evaluates to 0, which causes a runtime error because 0 is less than the corresponding current dimension (in my case, 20). This is the error:
HDF5-DIAG: Error detected in HDF5 (1.8.11) thread 0:
#000: H5S.c line 1388 in H5Screate_simple(): maxdims is smaller than dims
major: Invalid arguments to routine
minor: Bad value
I compiled one of the Fortran examples that came with HDF5 that uses the same H5S_UNLIMITED_F parameter (h5_extend.f90), but for that application, the parameter evaluates to -1 and there is no problem.
What might I be doing wrong?
Below is a test program I wrote to replicate the problem seen in my project:
program simple_test
use hdf5
implicit none
integer :: irank, hdferr
integer(hsize_t) :: ny, nx, nz
real, dimension(:,:,:), allocatable :: dset
character (len = 256) :: hdf_file, dlab
integer(hid_t) :: file_handle, mem_space, file_space, dset_handle
integer(hsize_t), dimension(:), allocatable :: dim_array, max_array
irank = 3
ny = 10
nx = 15
nz = 20
allocate (dset(ny, nx, nz))
hdf_file = 'simple_test.hdf5'
dlab = 'simple_data'
allocate (dim_array(irank))
allocate (max_array(irank))
dim_array = (/ ny, nx, nz /)
max_array = (/ ny, nx, H5S_UNLIMITED_F /)
print *, 'h5s_unlimited_f: ', h5s_unlimited_f
print *, 'dim_array: ', dim_array
print *, 'max_array: ', max_array
call h5open_f(hdferr)
if (hdferr .eq. -1) then
print *, 'Error opening HDF5 Fortran interface.'
end if
! Create a new file.
call h5fcreate_f(hdf_file, H5F_ACC_TRUNC_F, file_handle, hdferr)
if (hdferr .eq. -1) then
print *, 'Error creating HDF5 file.'
end if
! Create memory dataspace.
call h5screate_simple_f(irank, dim_array, mem_space, hdferr, max_array)
if (hdferr .eq. -1) then
print *, 'Error creating HDF5 memory dataspace.'
end if
! Create the dataset.
call h5dcreate_f(file_handle, trim(dlab), H5T_IEEE_F32LE, mem_space, &
dset_handle, hdferr)
if (hdferr .eq. -1) then
print *, 'Error creating HDF5 dataset.'
end if
! Create file dataspace.
call h5screate_simple_f(irank, dim_array, file_space, hdferr, max_array)
if (hdferr .eq. -1) then
print *, 'Error creating HDF5 file dataspace.'
end if
call h5dwrite_f(dset_handle, H5T_IEEE_F32LE, dset, dim_array, hdferr, &
mem_space, file_space)
if (hdferr .eq. -1) then
print *, 'Error writing HDF5 dataset.'
end if
call h5close_f(hdferr)
if (hdferr .eq. -1) then
print *, 'Error closing HDF5 Fortran interface.'
end if
deallocate (dset)
deallocate (dim_array)
deallocate (max_array)
end program simple_test
The first call to h5s_create_simple_f is what fails. If I change the memory dataspace to not use the max_array parameter (since it is optional and in my case perhaps unnecessary), then I still get the same error on the second call to h5s_create_simple_f.
I'm compiling as follows:
gfortran -c simple_test.f90 -o simple_test.o -I<hdf5_include_path>
gfortran -o simple_test simple_test.o -L<hdf5_lib_path> -lhdf5_fortran -lhdf5hl_fortran
I've also tried setting max_array(irank) to -1, but that yields an entirely different error.
(The original issue was that H5S_UNLIMITED_F is a variable that is initialised by a call to H5open_f, referencing it before that initialization is not permitted.)
Are you sure that the call to H5S_create_simple_f is what fails? Your traceback indicates an error from the dataset portion of the library.
I would expect a failure from dataset creation, because for variable sized datasets you need to specify the chunk size. Create a property list using H5Pcreate_f, then set the chunk size using H5Pset_chunk_f, then provide that property list after the error argument in the call to H5Dcreate_f. Comment if that doesn't make sense and I'll dig out an example.