This question already has answers here:
Line continuation of strings in Fortran
(4 answers)
Closed 4 years ago.
I have this code in FORTRAN 77 (I have to use this because it is used as a subroutine for my Abaqus program) where I am asking the subroutine to print my stresses and strain results, for each element and after each time increment, in a particular place. Now, my directory path is long (because of several reasons). Therefore, I have to write the path to the directory in two lines since FORTRAN 77 only recognizes anything written between columns 6 to 77 (I believe!).
Now, I have tried many things!
I have put & symbol at column 6 on the next line, a number (like 1) at column 6 on the next line, and even a star symbol (*) at the same place!
However, I keep getting error# 5082!
Here is the part of the code that is not being accepted in ifort compiler:
subroutine uvarm(uvar,direct,t,time,dtime,cmname,orname,
1 nuvarm,noel,npt,layer,kspt,kstep,kinc,ndi,nshr,coord,
2 jmac,jmatyp,matlayo,laccfla)
include 'aba_param.inc'
character*80 cmname, orname
character*3 flgray(15)
character*80 file1, file2
dimension uvar(nuvarm),direct(3,3),t(3,3),time(2)
dimension array(15),jarray(15),jmac(*),jmatyp(*),coord(*)
C integer i
call getvrm('E',array,jarray,flgray,jrcd,jmac,jmatyp,
1 matlayo,laccfla)
uvar(1) = array(1)
uvar(2) = array(2)
uvar(3) = array(4)
call getvrm('S',array,jarray,flgray,jrcd,jmac,jmatyp,
1 matlayo,laccfla)
uvar(4) = array(1)
uvar(5) = array(2)
uvar(6) = array(4)
file1 = '/gpfs/work/m/mfg5310/fracture/ResearchWork'
1 '/fracture_subroutines/frac_in_mid_Mode2_case1_strains.txt'
file2 = '/gpfs/work/m/mfg5310/fracture/ResearchWork'
2 '/fracture_subroutines/frac_in_mid_Mode2_case1_stress.txt'
open(unit=101,file=file1)
open(unit=103,file=file2)
write(101,350) uvar(1),uvar(2),uvar(3),coord(1),coord(2)
write(103,350) uvar(4),uvar(5),uvar(6),coord(1),coord(2)
350 format(e12.5,6x,e12.5,6x,e12.5,6x,e12.5,6x,e12.5)
C close(unit=101)
C close(unit=103)
return
end
What should I do?
I know I can always shorten the path so that the entire directory fits in one line. But for two reasons, I want to know how to continue the string into the next line in Fortran 77:
Reason 1: I just really want to know this.
Reason 2: The files printed are more organized this way! I will be able to name the file exactly what I want to.
Simply use the Fortran string concatenation operator // like this
file1 = '/gpfs/work/m/mfg5310/fracture/ResearchWork'//
& '/fracture_subroutines/frac_in_mid_Mode2_case1_strains.txt'
Related
I am trying to read a file called "syerasg.txt" in Fortran90. This text file includes panel data on 91 variables (columns) for 8984 individuals for 16 years (143 744 rows). This variables are divided in 7 groups and this groups are divided in 13 subgroups. I am trying to read this file with the following code:
PROGRAM main
IMPLICIT NONE
INTEGER, PARAMETER :: p=8984, tf=16, sem=53, emp=7, gap=13
INTEGER :: r, t, j, m, g, x, i, IOstatus
INTEGER, DIMENSION (p,tf,emp) :: yemp
INTEGER, DIMENSION (p,tf,emp,gap) :: gaps
OPEN(UNIT=4, FILE='syearsg.txt',STATUS='old') !start gap years
DO i=1,p
DO t=1,tf
DO j=1,emp
IF (j==1) THEN
READ(4,*)(gaps(i,t,j,g),g=1,13)
ELSE IF (j==2) THEN
READ(4,*)(gaps(i,t,j,g-13),g=14,26)
ELSE IF (j==3) THEN
READ(4,*)(gaps(i,t,j,g-26),g=27,39)
ELSE IF (j==4) THEN
READ(4,*)(gaps(i,t,j,g-39),g=40,52)
ELSE IF (j==5) THEN
READ(4,*)(gaps(i,t,j,g-52),g=53,65)
ELSE IF (j==6) THEN
READ(4,*)(gaps(i,t,j,g-65),g=66,78)
ELSE IF (j==7) THEN
READ(4,*)(gaps(i,t,j,g-78),g=79,91)
END IF
END DO
END DO
END DO
CLOSE(4)
END PROGRAM main
When, running the code I get the following message:
Fortran runtime error: End of file
Any ideas on how to solve this?
Your loop nest issues 1,006,208 (that is p*tf*emp) read statements. It's no surprise that the program runs past the end of a file with only 143,744 lines. read reads the values it is asked to read, then skips to the start of the next line ready for the next read.
You might be able to fix your program by fiddling around with non-advancing input, ie telling the read statements not to skip to the start of the next line. But it would be easier not to.
From what you write you should only be issuing p*tf read statements, then reading a single line containing 91 elements, then distributing those elements into gaps as your logic demands.
You might revise your code to something like this (untested and not very carefully checked)
INTEGER, DIMENSION(91) :: workvec
...
DO i=1,p
DO t=1,tf
READ(4,*) workvec
gaps(i,t,1,1:13) = workvec( 1:13)
gaps(i,t,2,1:13) = workvec(14:26)
...
END DO
END DO
For example, I have a write command to save an array with 6 fields in a text file like this:
OPEN(UNIT=26,FILE='W:\Partikeltemperaturfeld.txt',
&FORM ='FORMATTED',STATUS='UNKNOWN',
&ACTION='READWRITE')
C
WRITE (26,FMT='(6(F8.3,3X))') TFIELD(1,1:6)
C
REWIND(26)
Now I want to read and save the 6 values of the last line of my text file in another array with 6 fields like:
IOS = 0
DO WHILE (IOS.EQ.0)
READ(UNIT=26,FMT='(6(F8.3,3X))',IOSTAT=IOS) TEST(1:6)
END DO
This could be the content of the last line in my file:
1377.445 1373.171 1363.639 1352.062 1341.476 1334.764
The aim is to save the last line in existing format.
But after doing this I always get values 0.000000E+00. How can I read and save the last line of my 'W:\Partikeltemperaturfeld.txt' file in array TEST(1:6)?
If you do
DO WHILE (IOS.EQ.0)
READ(UNIT=26,FMT='(6(F8.3,3X))',IOSTAT=IOS) TEST(1:6)
END DO
the loop will exit when there was some problem (end of file or an error condition) reading the array in the input list. The value of the variable being read is than undefined. You cannot use it. It can contain anything.
BTW your code is not Fortran 77 conforming (it is Fortran 90 or later) so I will not try to make my suggestion 100% Fortran 77 either. You can do
DO
READ(UNIT=26,FMT='(6(F8.3,3X))',IOSTAT=IOS) TMP
IF (IOS.EQ.0) THEN
TEST = TMP
ELSE
EXIT
END DO
END DO
where TEST and TMP are arrays of size 6
REAL FUNCTION PHI(D)
COMMON FAC,DELTA,ER,T
DOW=2.*D/DELTA
TOW=4.*T/DELTA
DOWM=DOW-1.
DOWP=DOW+1.
IF(D.EQ.0.) GO TO 1
PHI=DOWM*ALOG(DOWM)-DOWP*ALOG(DOWP)
1-0.5*DOWM*ALOG(DOWM**2+TOW**2)
2+0.5*DOWP*ALOG(DOWP**2+TOW**2)
3-TOW*(ATAN(DOWM/TOW)-ATAN(DOWP/TOW))
PHI=PHI*FAC/2.
GO TO 2
PHI=FAC*(0.5*ALOG(1.+TOW*TOW)+TOW*ATAN(1./TOW))
CONTINUE
RETURN
END
My homework is to convert above code into Matlab .m file.
But I couldnt understand and I have never seen an implementation like this:
....
PHI=DOWM*ALOG(DOWM)-DOWP*ALOG(DOWP)
1-0.5*DOWM*ALOG(DOWM**2+TOW**2)
2+0.5*DOWP*ALOG(DOWP**2+TOW**2)
3-TOW*(ATAN(DOWM/TOW)-ATAN(DOWP/TOW))
...
There is not any line continuation mark! This is very confusing.
How should I convert these lines into Matlab code? I know Matlab but I dont know Fortran.
The PHI Calculation is in four lines, the second line is marked with 1, and so on ...
Those are the continuation marks you are looking for (1, 2, 3)
Your formula is:
PHI=DOWM*ALOG(DOWM)-DOWP*ALOG(DOWP)-0.5*DOWM*ALOG(DOWM**2+TOW**2)+0.5*DOWP*ALOG(DOWP**2+TOW**2)-TOW*(ATAN(DOWM/TOW)-ATAN(DOWP/TOW))
But remember that original Fortran can not understand characters form column 73 and up (only 1 to 72) that is why the use of continuation marks in column 6 (normally is asterisk, but numbers can be used too).
Also code only can be between columns 7 to 72, because columns 1 to 5 are reserved for labels.
My Guess is that label 1 is in front of the second definition of PHI, and the label 2 in front of the CONTINUE, this is how should look in Fortran
GO TO 2
1 PHI=FAC*(0.5*ALOG(1.+TOW*TOW)+TOW*ATAN(1./TOW))
2 CONTINUE
The code in Fortran should be something like this:
REAL FUNCTION PHI(D)
COMMON FAC,DELTA,ER,T
DOW=2.*D/DELTA
TOW=4.*T/DELTA
DOWM=DOW-1.
DOWP=DOW+1.
IF(D.EQ.0.) GO TO 1
PHI=DOWM*ALOG(DOWM)-DOWP*ALOG(DOWP)
1-0.5*DOWM*ALOG(DOWM**2+TOW**2)
2+0.5*DOWP*ALOG(DOWP**2+TOW**2)
3-TOW*(ATAN(DOWM/TOW)-ATAN(DOWP/TOW))
C
C Previous four (4) lines have this formula (C mark for comment)
C
C PHI=DOWM*ALOG(DOWM)-DOWP*ALOG(DOWP)-0.5*DOWM*ALOG(DOWM**2+TOW**2)+0.5*DOWP*ALOG(DOWP**2+TOW**2)-TOW*(ATAN(DOWM/TOW)-ATAN(DOWP/TOW))
C
PHI=PHI*FAC/2.
GO TO 2
1 PHI=FAC*(0.5*ALOG(1.+TOW*TOW)+TOW*ATAN(1./TOW))
2 CONTINUE
RETURN
END
I have some issues about opening and reading multiple files. I have to write a code which reads two columns in n files formatted in the same way (they are different only for the values...). Before this, I open another input file and an output file in which I will write my results. I read other questions in this forum (such as this one) and tried to do the same thing, but I receive these errors:
read(fileinp,'(I5)') i-49
1
devstan.f90:20.24:
fileLoop : do i = 50,52
2
Error: Variable 'i' at (1) cannot be redefined inside loop beginning at (2)
and
read(fileinp,'(I5)') i-49
1
Error: Invalid character in name at (1)
My files are numbered from 1 to n and are named 'lin*27-n.dat' (where n is the index starts from 1) and the code is:
program deviation
implicit none
character(len=15) :: filein,fileout,fileinp
integer :: row,i,h
real :: usv,usf,tsv,tsf,diff
write(*,'(2x,''Input file .......''/)')
read(*,'(a12)') filein
write(*,'(2x,''Output file........''/)')
read(*,'(a12)') fileout
open(unit = 30,File=filein)
open(unit = 20,File=fileout)
fileLoop : do i = 50,52
fileinp = 'lin*27-'
read(fileinp,'(I5)') i-49
open(unit = i,File=fileinp)
do row = 1,24
read(30,*) h,usv,tsv
read(i,*) h,usf,tsf
diff = usf - usv
write(20,*) diff
enddo
close(i)
enddo fileLoop
end program deviation
How can I solve it? I am not pro in Fortran, so please don't use difficult language, thanks.
The troublesome line is
read(fileinp,'(I5)') i-49
You surely mean to do a write (as in the example linked): this read statement attempts to read from the variable fileinp rather than writing to it.
That said, simply replacing with write is probably not what you need either. This will ignore the previous line
fileinp = 'lin*27-'
merely setting to, in turn, "1", "2", "3" (with leading blanks). Something like (assuming you intend that * to be there)
write(fileinp, '("lin*27-",I1)') i-49
Note also the use of I1 in the format, rather than I5: one may want to avoid blanks in the filename. [This is suitable when there is exactly one digit; look up Iw.m and I0 when generalizing.]
This question already has answers here:
Convert integers to strings to create output filenames at run time
(9 answers)
Closed 7 years ago.
I am using Fortran to do calculation on huge data set which was split into many files. The names of the files are:
maltoLyo12per-reimage-set1.traj
maltoLyo12per-reimage-set2.traj
maltoLyo12per-reimage-set3.traj
The code I wrote to do the calculation is as below:
fileLoop: do j = 31, 34
OPEN(unit=31,status='old',file=fileplace//'maltoLyo12per-reimage-set1.traj')
OPEN(unit=32,status='old',file=fileplace//'maltoLyo12per-reimage-set2.traj')
OPEN(unit=33,status='old',file=fileplace//'maltoLyo12per-reimage-set3.traj')
OPEN(unit=34,status='old',file=fileplace//'maltoLyo12per-reimage-set4.traj')
... operation....
close (j)
end do fileLoop
During the run I want the code to open each file at a time and close them after finish calculation. But the above code will open all the files at once and close them one after one upon finish calculation.
So I tried to alter the code something like below:
fileLoop: do j = 31, 34
OPEN(unit=j,status='old',file=fileplace//'maltoLyo12per-reimage-set1.traj')
close (j)
end do fileLoop
But here I am facing a problem with the file name. Each time the loop run, the file name doesn't change because of the phrase "set1" in the file name. I want the number in the file name to change like set1, set2, set3, etc., subsequently with file unit number 31,32,33,34, etc.
Something like this: (edited to have unit numbers 31 to 34, filenames 1 to 4.)
character (len=90) :: filename
fileLoop: do j = 31, 34
write (filename, '( "maltoLyo12per-reimage-set", I1, ".traj" )' ) j - 30
OPEN(unit=j,status='old',file=filename)
close (j)
end do fileLoop