How do I use this code in Fortran 77? - fortran

This question Reading freely available UVR data using gfortran on mac OSX is what I was trying to figure out. I am not on a Mac so I don't know how they got it to work. I am using the g77 compiler.
I don't understand how I have to modify this script to make it work for my file. The script is available here.
- Read header (size= pixel size *2byte):
character head*14400
read(10,rec=1) head
read(head,'(2i6,2f8.2,f8.4,2e12.5,a1,a8,a1,a40)')
& npixel,nline,lon_min,lat_max,reso,slope,offset,',',
& para,',',outfile
- Read data (e.g., fortran77)
parameter(nl=7200, ml=3601)
... open file by "unformatted", "recl=nl*2(byte)" (,"bytereclen")
integer*2 i2buf(nl,ml)
do m=1,ml
read(10,rec=1+m) (i2buf(n,m), n=1,nl)
do n=1,nl
par=i2buf(n,m)*slope+offset
write(6,*) 'PAR[Ein/m^2/day]=',par
enddo
enddo

Related

Fortran inquire return internal file

I have a situation unexpected with my fortran program.
I want to drop some data in a text file. For some reasons, I created a type to deal with this file.
Therefore, I open a file with the commands (where f is my file type object):
open(newunit = f%unit, &
file = trim(adjustl(f%name)), &
form = 'FORMATTED', &
access = 'STREAM', &
action = 'WRITE', &
status = 'REPLACE', &
iostat = ios)
if(ios /= 0) print '("Problem creating file")', trim(f%name)
Then I write stuff like this:
write(unit=f%unit,fmt='(100A)') "#Header"
And when it is done, I want to close the file. To do this, I call the subroutine:
subroutine close_file_ascii(f)
implicit none
class(my_file_type) intent(in) :: f
logical :: file_opened, file_exist
integer :: ios
inquire(unit=f%unit, exist=file_exist, opened=file_opened) !, iostat=ios)
print *,'file_exist:', file_exist, 'file_opened:', file_opened, 'ios:', ios
if ((file_opened) .and. (file_exist)) then
close(unit=f%unit)
else
print *,"[WARNING]"
end if
end subroutine close_file_ascii
My problem is in this last subroutine. When I run the program on windows, I get the following error:
Fortran runtime error: Inquire statement identifies an internal file
Error termination. Backtrace
Therefore, I tried to create MWE to understand the problem, but all of them where working well. So couldn't really isolate the problem. Also a strange thing is that when I compile and execute with gfortran on my linux there is no problem, but when I do so on my windows I get the previous error. ( I compile on windows with gfortran version 7.3.0 x86_64-posix-sjlj-rev0, Built by MinGW-W64 )
I already work-around this problem by uncommenting the end of inquire line in the close subroutine, and everything seems to work fine. And I get the following print:
file_exist: T file_opened: T ios: 5018
But I would to understand what is going on. So what could create such internal file error (while the file should not be internal but external)? Is my workaround could be harmful ? Is it a bug ? Is there a better way to close safely an opened file? Any ideas to isolate the problem ?
EDIT
From roygvib's comment, the following test seems to replicate the problem:
program bug
implicit none
integer :: i
character(len=1) :: s
write (s,'(i1)') 0
open(newUnit=i,file='bug.txt',status='unknown')
inquire(unit=i)
end program bug
The update to gfortran 8.1 solved the problem.

ABAQUS fortran subroutine write command doesn't write anything

I need to save an Abaqus simulation output to an external file. To do this I tried to use a subroutines but I saw it doesn't print anything. I did some test using this code:
SUBROUTINE UMAT(STRESS,STATEV,DDSDDE,SSE,SPD,SCD,
1 RPL,DDSDDT,DRPLDE,DRPLDT,
2 STRAN,DSTRAN,TIME,DTIME,TEMP,DTEMP,PREDEF,DPRED,CMNAME,
3 NDI,NSHR,NTENS,NSTATV,PROPS,NPROPS,COORDS,DROT,PNEWDT,
4 CELENT,DFGRD0,DFGRD1,NOEL,NPT,LAYER,KSPT,JSTEP,KINC)
C
INCLUDE 'ABA_PARAM.INC'
C
CHARACTER*80 CMNAME
DIMENSION STRESS(NTENS),STATEV(NSTATV),
1 DDSDDE(NTENS,NTENS),DDSDDT(NTENS),DRPLDE(NTENS),
2 STRAN(NTENS),DSTRAN(NTENS),TIME(2),PREDEF(1),DPRED(1),
3 PROPS(NPROPS),COORDS(3),DROT(3,3),DFGRD0(3,3),DFGRD1(3,3),
4 JSTEP(4)
C user coding to define DDSDDE, STRESS, STATEV, SSE, SPD, SCD
C and, if necessary, RPL, DDSDDT, DRPLDE, DRPLDT, PNEWDT
C
OPEN (UNIT=1, FILE='D:\Temp\workspace\fortan\data_fortran.dat',
1 STATUS='UNKNOWN', ACCESS='DIRECT',FORM='FORMATTED')
WRITE (1,*) 'WRITE TEST'
CLOSE (1)
RETURN
END
-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-°-
SUBROUTINE UGENS(DDNDDE,FORCE,STATEV,SSE,SPD,PNEWDT,STRAN,
1 DSTRAN,TSS,TIME,DTIME,TEMP,DTEMP,PREDEF,DPRED,CENAME,NDI,
2 NSHR,NSECV,NSTATV,PROPS,JPROPS,NPROPS,NJPROP,COORDS,CELENT,
3 THICK,DFGRD,CURV,BASIS,NOEL,NPT,KSTEP,KINC,NIT,LINPER)
C
INCLUDE 'ABA_PARAM.INC'
C
CHARACTER*80 CENAME
DIMENSION DDNDDE(NSECV,NSECV),FORCE(NSECV),STATEV(NSTATV),
1 STRAN(NSECV),DSTRAN(NSECV),TSS(2),TIME(2),PREDEF(*),
2 DPRED(*),PROPS(*),JPROPS(*),COORDS(3),DFGRD(3,3),
3 CURV(2,2),BASIS(3,3)
C
logical, save :: isFileOpen = .FALSE.
C
CALL GETVRM('TEMP',ARRAY,JARRAY,FLGRAY,JRCD,JMAC,JMATYP,MATLAYO,
1LACCFLA)
C IS THE FILE OPEN?
if (.not. isFileOpen) then
OPEN (UNIT=1, FILE='D:\Temp\workspace\fortan\data.txt',
1 STATUS='NEW')
C CHANGE FILE FLAG
isFileOpen = .TRUE.
end if
write (1,*) 'WRITE TRY'
RETURN
END
The simulation runs without any error but it doesn't write the file, regardless the results (it doesn't print a text).
I thought it could be a link error but everything seems to be ok:
I am using:
Abaqus 6.14
Parallel Studio XE 2013
Intel Composer XE 2013
and all
abaqus verify -user_std
abaqus info=system
abaqus verify -all
gave me PASS.
I don't really know where could be the error. Does anyone have any idea?
I would try to write to an already available channel. For instance in UMAT, Write(6,) prints the Gauss Point info to the .dat file while write(7,) prints to the .msg file. Such procedure may seem a good approach while debugging . When you want info only at the end of each converged increment you may want to pass info to the uexternal routine by common blocks and loop over GP in that routine.
An even better approach is to create SDVs and check them at the odb via UI. In that case you need to declare in the input file how many sdvs you want to pass to the the odb.

Fortran 90 runtime error:end of file

I'm sorry if this has been asked before, but I couldn't find an answer that seemed to work for me. I'm working with an old program, but have made a few modifications to it.
I can include the whole 2500 line program, but it seems like that is a lot.
I've successfully compiled the a program, but it fails when I try and run it. I'm getting a "Fortran runtime error: End of file" at the line which reads the .dat file. I've tried to compile a test segment, using the same .dat file and same variables. It results in the same problem.
PROGRAM OPEN
INTEGER (KIND=1), PARAMETER :: dy=3 ! number of income states
INTEGER (KIND=2) :: OpenStatus
REAL, DIMENSION(dy) :: grid,wt
OPEN(1,file='cygdrive/user/mk.dat',status='old',form='formatted',IOSTAT=OpenStatus)
READ (1,*) grid, wt
IF(OpenStatus>0) STOP 'cannot open mk.dat'
CLOSE(1)
PRINT*, grid(1)
END PROGRAM
The data file referenced is:
-1.7320508e+000
0.0000000e+000
1.7320508e+000
4.1777138e-001
1.6710855e+000
4.1777138e-001
Where each of these numbers is on its own line and preceeded by a space
This generates the same end of file runtime error. I'd really appreciate any help here.
I should add that I compiled with gfortran.
EDIT:
As per High Performance Mark's suggestion below, I've modified it to include an inquire test.
PROGRAM TEST
CHARACTER :: fnm, seq, fort
Logical :: lex
INTEGER (KIND=1), PARAMETER :: dy=3 ! number of income states
INTEGER (KIND=2) :: j,j0,j1,j2,j4,j5,j6,j7,k,jjj,jj,dyy,OpenStatus
REAL, DIMENSION(dy) :: grid,wt
OPEN(1,file='cygdrive/user/mk.dat',status='old',form='formatted',IOSTAT=OpenStatus)
INQUIRE (1, EXIST=lex, NAME=fnm, SEQUENTIAL=seq, FORMATTED=fort)
PRINT*, 'Exists=',lex, ' Name=',fnm, ' Sequential=', seq, 'Formatted=', fort
READ (1,*) grid, wt
IF(OpenStatus>0) STOP 'cannot open mk.dat'
CLOSE(1)
PRINT*, grid(1)
END PROGRAM
The results of the inquire statement are:
Exists= T Name= Sequential=U Formatted=U
My understanding is that the File is found (i.e. exists is returned as true), is un-named and the format and sequential access are returned as unknown (as is direct which I included later). I've also checked the delimiter and padding which are coming back as unknown.
My beginner intuition is telling me that I should try and create a new data file by writing to it with a fortran program and that should solve the problem? Is that correct? If so is there a fundamental misunderstanding at play here i.e. is this a problem with data files from other sources?
Thanks for all your patience.
(Answered in the comments. See Question with no answers, but issue solved in the comments (or extended in chat) )
The OP wrote:
I've fixed this problem-the program was looking for it in a different place, I've now corrected that.

Differences when writing to / reading from the console between gfortran- and g77-compiled code

This one's going to take a bit of explaining. Please bear with me.
What I Have
I have in my possession some Fortran source code and some binaries that have been compiled from that code. I did not do the compilation, but there is a build script that suggests G77 was used to do it.
As well as the Fortran stuff, there is also some Java code that provides users with a GUI "wrapper" around the binaries. It passes information between itself and the binaries via their input/output/error pipes. The Java code is very messy, and this way of doing things adds a lot of boilerplate and redundancy, but it does the job and I know it works.
What I Need
Unfortunately, I'd like to make some changes:
I want to create a new Python wrapper for the binaries (or, more precisely, extend an existing Python program to become the new wrapper).
I want to be able to compile the Fortran code as part of this existing program's build process. I would like to use gfortran for this, since MinGW is used elsewhere in the build and so it will be readily available.
The Problem
When I compile the Fortran code myself using gfortran, I cannot get the resulting binaries to "talk" to either the current Java wrapper or my new Python wrapper.
Here are the various ways of printing to the console that I have tried in the Fortran code:
subroutine printA(message)
write(6,*) message
end
subroutine printB(message)
write(*,*) message
end
subroutine printC(message)
use iso_fortran_env
write(output_unit,*) message
end
There are also read commands as well, but the code doesn't even get a change to execute that part so I'm not worrying about it yet.
Extra Info
I have to call gfortran with the -ffixed-line-length-132 flag so that the code compiles, but apart from that I don't use anything else. I have tried using the -ff2c flag in the vague hope that it will make a difference. It doesn't.
This stackoverflow post is informative, but doesn't offer me anything that works.
The relavant manual page suggests that printA should work just fine.
I'm working on Windows, but will need this to be multi-platform.
Juse in case you're intested, the Java code uses Runtime.getRuntime().exec("prog.exe") to call the binaries and then the various "stream" methods of the resulting Process object to communicate with them. The Python code uses equivalents of this provided by the Popen object of the subprocess module.
I should also say that I am aware there are alternatives. Rewriting the code in Python (or something else like C++), or making amendments so that is it can be called via F2Py have been ruled out as options. Using g77 is also a no-go; we have enough dependencies as it is. I'd like to be able to write to / read from the console properly with gfortran, or know that it's just not possible.
Hard to say without seeing more details from your Fortran and Python codes. The following pair of code works for me (at least under Linux):
Fortran program repeating its input line by line prefixed with line number:
program test_communication
use iso_fortran_env, stdout => output_unit, stdin => input_unit
implicit none
character(100) :: buffer
integer :: ii
ii = 1
do while (.true.)
read(stdin, *) buffer
write(stdout, "(I0,A,A)") ii, "|", trim(buffer)
flush(stdout)
ii = ii + 1
end do
end program test_communication
Python program invoking the Fortran binary. You can feed it with arbitrary strings from the console.
import subprocess as sub
print "Starting child"
proc = sub.Popen("./a.out", stdin=sub.PIPE, stdout=sub.PIPE)
while True:
send = raw_input("Enter a string: ")
if not send:
print "Exiting loop"
break
proc.stdin.write(send)
proc.stdin.write("\n")
proc.stdin.flush()
print "Sent:", send
recv = proc.stdout.readline()
print "Received:", recv.rstrip()
print "Killing child"
proc.kill()

Opening multiple files in Fortran 90

I would like to open 10,000 files with file names starting from abc25000 until abc35000 and copy some information into each file. The code I have written is as below:
PROGRAM puppy
IMPLICIT NONE
integer :: i
CHARACTER(len=3) :: n1
CHARACTER(len=5) :: cnum
CHARACTER(len=8) :: n2
loop1: do i = 25000 ,35000 !in one frame
n1='abc'
write(cnum,'(i5)') i
n2=n1//cnum
print*, n2
open(unit=i ,file=n2)
enddo loop1
end
This code is supposed to generate files starting from abc24000 until abc35000 but it stops about half way saying that
At line 17 of file test-openFile.f90 (unit = 26021, file = '')
Fortran runtime error: Too many open files
What do I need to do to fix the above code?
This limit is set by your OS. If you're using a Unix/Linux variant, you can check the limit using from the command line using ulimit -n, and raise it using ulimit -n 16384. You'll need to set a limit greater than 10000 to allow for all the other files that the shell will have open. You may also need admin privileges to do this.
I regularly bump the limit up to 2048 to run Fortran programs, but never as high as 10000. However, I echo the other answers that, if possible, it's better to restructure your program to close each file before opening the next.
You need to work on the files one at a time (or in small groups that do not exceed the limitation imposed by the operating system).
for each file:
open file
write
close file
Operating systems tend to have limits on resources. Typically on, for instance, Linux, there is by default a limit of 1024 file descriptors per process. The error message you're getting is just the Fortran runtime library passing information upwards that it was unable to open yet another file due to an OS error.