How to add a header in a output file in Fortran - header

I just want to add a header in my output file.
program deltatheta
implicit none
integer :: i, yminpos
integer, parameter :: Ny=100000, Nloop=43795
real(8), allocatable, dimension(:) :: y,U
real(8), allocatable, dimension(:) :: yinf,bb,cc
real(8) :: ymax,aa,ymin,Umin,Uinf,hr,theta2,Integ,delta2,l0,l2,l3
Uinf=1.d0 !U at infinity
ymax=80.d0 !Coordinate y at infinity
aa=2.d0
allocate (y(Ny),U(Ny),yinf(Nloop),bb(Nloop),cc(Nloop))
open(unit=10,file='Data/loop.dat')
do i = 1,Nloop
read(10,*) bb(i),cc(i),l0,yinf(i),l2,l3
enddo
close(10)
open(unit=12,file='Data/loop_thetanew.dat')
write(12,*) 'd','b','theta2','yinf/theta2'
do i = 1,Nloop
call mesh(Ny,ymax,y)
call velocity(Ny,y,aa,bb(i),cc(i),yminpos,U,Umin,ymin,hr)
call theta1(Ny,Uinf,ymax,y,yminpos,U,Umin,Integ)
theta2 = Integ + y(yminpos)
write(12,*) bb(i),cc(i),theta2,yinf(i)/theta2
enddo
close(12)
endprogram
I just use write function but I know this not the best way.
The final result of my output file is:
dbtheta2yinf/theta2
8.0000000000000000 0.10000000000000001 2.2362553308691373 1.7887089836339782
What I have to do in my code to obtain some like this:
d b theta2 yinf/theta2
8.0000000000000000 0.10000000000000001 2.2362553308691373 1.7887089836339782

What I have to do in my code to obtain some like this:
d b theta2 yinf/theta2
8.0000000000000000 0.10000000000000001 2.2362553308691373 1.7887089836339782
Short answer, you have to do formatted I/O. #HighPerformanceMark and #johncampbell gave good suggestions in the comments and you can find much more detailed info in the Fortran Standards or in your compiler docs, whichever it is. I'll not dive deep into this theme (will let you free for doing your research).
But I'll adress your specific issue - correctly spacing your header tags to match the data's output lengths - with a simple proposal (that, again, do not supress the proper definition of a set of i/o formatting rules that fit your needs). From the old Oracle compiler docs:
Unformatted I/O is used to transfer binary information to or from
memory locations without changing its internal representation. Each
execution of an unformatted I/O statement causes a single logical
record to be read or written. Since internal representation varies
with different architectures, unformatted I/O is limited in its
portability.
You can use unformatted I/O to write data out temporarily, or to write
data out quickly for subsequent input to another FORTRAN program
running on a machine with the same architecture.
Basically, I am putting your header strings inside an array with a defined length (in this case, I'm considering 26 because this is the length of the unformatted outuput sample you provided, but you should adjust it if you decide to a different record length). The reason to do so is that Fortran adds trail blanks into the right of the character variables by default, so in effect they get them left justified.
write(12, '(4a26)') [character(26) :: 'd', 'b', 'theta2', 'yinf / theta2']
Up to now, you are getting this output:
d b theta2 yinf/theta2
8.0000000000000000 0.10000000000000001 2.2362553308691373 1.7887089836339782
The leading and trailing blanks on the real values were put there by the compiler specific unformatted output, to take account of negative sign, exponents and other stuff. The only way to get rid of them is by doing formatted i/o.
Just for completness, if you really want the default unformatted output to be left aligned like the header, you could write then to string variables, align, then write to file. I will not enter on this because, as far as I know, data transfer to an internal file demands formatted, so you should not rely on this working everywhere (I couldn't find this restriction on the Fortran Standard, but all compiler doc pages I know state this).
The closest thing you could get with formatted write is:
character(26) :: recs(4)
! (...)
write(recs, '(4g26.17)') bb(i), cc(i), theta2, yinf(i) / theta2
write(12, '(4a26)') adjustl(recs)
That would result into this:
d b theta2 yinf/theta2
8.0000000000000000 0.10000000000000001 2.2362553308691373 1.7887089836339782
Another option, but less reliable, is:
write(12, '(t1,g0,t27,g0,t53,g0,t79,g0)') bb(i), cc(i), theta2, yinf(i) / theta2
That will produce this with gfortran 8.0:
d b theta2 yinf/theta2
8.0000000000000000 0.10000000000000001 2.2362553308691373 1.7887089836339782
But this with ifort 18.0
d b theta2 yinf/theta2
8.000000000000000 .1000000000000000 2.236255330869137 1.788708983633978

Related

Formatting in Raku

I have written a function that outputs a double, upto 25 decimal
places. I am trying to print it as a formatted output from Raku.
However, the output is incorrect and truncated.
See MWE:
my $var = 0.8144262510988963255087469;
say sprintf("The variable value is: %.25f", $var)
The above code gives The variable value is: 0.8144262510988963000000000 which is not what is expected.
Also, this seems weird:
my $var = 0.8144262510988963255087469;
say $var.Str.chars; # 29 wrong, expected 27
I tested the same in C:
#include <stdio.h>
int main() {
double var = 0.8144262510988963255087469;
printf("The variable value is: %.25lf \n", var);
return 0;
}
However, it works fine. Given the identical nature of sprintf and printf, I expected this C example to work in Raku too. Seems like %lf is not supported.
So is there a workaround to fix this?
I think this is actually a bug in how Rat literals are created. Or at least as WAT :-).
I actually sort of expect 0.8144262510988963255087469 to either give a compile time warning, or create a Num, as it exceeds the standard precision of a Rat:
raku -e 'say 0.8144262510988963255087469'
0.814426251098896400086204416
Note that these are not the same.
There is fortunately an easy workaround, by creating a FatRat
$ raku -e 'say 0.8144262510988963255087469.FatRat'
0.8144262510988963255087469
FWIW, I think this is worthy of creating an issue
From your question:
I have written a function that outputs a double, upto 25 decimal places.
From google:
Double precision numbers are accurate up to sixteen decimal places
From the raku docs :
When constructing a Rat (i.e. when it is not a result of some mathematical expression), however, a larger denominator can be used
so if you go
my $v = 0.8144262510988963255087469;
say $v.raku;
#<8144262510988963255087469/10000000000000000000000000>
it works.
However, do a mathematical expression such as
my $b = $a/10000000000000000000000000;
and you get the Rat => Num degradation applied unless you explicitly declare FatRats. I visualise this as the math operation placing the result in a Num register in the CPU.
The docs also mention that .say and .put may be less faithful than .raku, presumably because they use math operations (or coercion) internally.
Sorry to be the bearer of bad news, but 10**25 > 2 **64, but what you report as an issue is correct & (fairly) well documented behaviour given the constraints of double precision IEEE P754.

Read free format with no advance

In a given file record, I need to read the first two integer elements at first, and then the rest of the line (a large number of real elements), because the assignment depend on the first 2. Suppose the format of the first two integer elements is not really well defined.
The best way to solve the problem could be something:
read(unitfile, "(I0,I0)", advance='no') ii, jj
read(unitfile,*) aa(ii,jj,:)
But it seems to me the "(I0)" specification is not allowed in gfortran.
Basically the file read in unitfile could be something like:
0 0 <floats>
0 10 <floats>
10 0 <floats>
100 0 <floats>
100 100 <floats>
which is hard to be read with any fortran-like fixed field format specification.
Is there any other way to get around this, apparently trivial, problem?
This applies string manipulations to get the individual components, separated by blanks ' ' and/or tabs (char(9)):
program test
implicit none
character(len=256) :: string, substring
integer :: ii, jj, unitfile, stat, posBT(2), pos
real, allocatable :: a(:)
open(file='in.txt', newunit=unitfile, status='old' )
read(unitfile,'(a)') string
! Crop whitespaces
string = adjustl(trim(string))
! Get first part:
posBT(1) = index(string,' ') ! Blank
posBT(2) = index(string,char(9)) ! Tab
pos = minval( posBT, posBT > 0 )
substring = string(1:pos)
string = adjustl(string(pos+1:))
read(substring,*) ii
! Get second part:
posBT(1) = index(string,' ') ! Blank
posBT(2) = index(string,char(9)) ! Tab
pos = minval( posBT, posBT > 0 )
substring = string(1:pos)
string = adjustl(string(pos+1:))
read(substring,*) jj
! Do stuff
allocate( a(ii+jj), stat=stat )
if (stat/=0) stop 'Cannot allocate memory'
read(string,*) a
print *,a
! Clean-up
close(unitfile)
deallocate(a)
end program
For a file in.txt like:
1 2 3.0 4.0 5.0
This results in
./a.out
3.00000000 4.00000000 5.00000000
NOTE: This is just a quick&dirty example, adjust it to your needs.
[This answer has been significantly revised: the original was unsafe. Thanks to IanH for pointing that out.]
I generally try to avoid doing formatted input which isn't list-directed, when I can afford it. There's already an answer with string parsing for great generality, but I'll offer some suggestions for a simpler setting.
When you are relaxed about trusting the input, such as when it's just the formatting that's a bit tricky (or you 're happy leaving it to your compiler's bounds checking), you can approach your example case with
read(unitfile, *) ii, jj, aa(ii, jj, :)
Alternatively, if the array section is more complicated than given directly by the first two columns, it can be by an expression, or even by functions
read(unitfile, *) ii, jj, aa(fi(ii,jj), fj(ii,jj), :fn(ii,jj))
with pure integer function fi(ii,jj) etc. There is even some possibility of having range validation in those functions (returning a size 0 section, for example).
In a more general case, but staying list-directed, one could use a buffer for the real variables
read(unitfile, *) ii, jj, buffer(:) ! Or ... buffer(:fn(ii,jj))
! Validate ii and jj before attempting to access aa with them
aa(.., .., :) = buffer
where buffer is of suitable size.
Your first considered approach suggests you have some reasonable idea of the structure of the lines, including length, but when the number of reals is unknown from ii and jj, or when the type (and polymorphism reading isn't allowed) is not known, then things do indeed get tricky. Also, if one is very sensitive about validating input, or even providing meaningful detailed user feedback on error, this is not optimal.
Finally, iostat helps.

Reading complex array and vector from TXT file in FORTRAN90

I'm trying to write a subroutine in a module that I can include in various codes to read data from a given file. I have several codes (numerical algorithms) which will be reading the data from the file.
The file has the following format:
First entry: No. of rows and columns of my array of data (e.g. 720)
First n(=720) entries: entire first row of the matrix A
Second n(=720) entries: entire 2nd row of the matrix A
etc.
Last n(=720) entries: all n entries of vector b
Each entry has two columns, one for the REAL part of the number, the other for the COMPLEX part.
In summary, an example basic input file:
2
-0.734192049E+00 0.711486186E+01
0.274492957E+00 0.378855374E+01
0.248391205E-01 0.412154039E+01
-0.632557864E+00 0.195397735E+01
0.289619736E+00 0.895562183E+00
-0.284756160E+00 -0.892163111E+00
where the first entry says its a 2x2 matrix and 2x1 vector
The first 4 lines are the four entries of the matrix A (left column Real, right column Imag.)
The last 2 lines are the two entries of the vector b (left column Real, right column Imag.)
I have written the following code to try and implement this but it simply outputs the wrong results:
n= 2
A= ( 0.0000000 , 1.08420217E-19) (-9.15983229E-16, 3.69024734E+19) ( 1.26116862E-43, 0.0000000 ) ( 0.0000000 , 0.0000000 )
b= ( 0.0000000 , 1.08420217E-19) ( 0.0000000 , 1.08420217E-19)
With the code:
SUBROUTINE matrix_input(n,A,b)
IMPLICIT NONE
!
INTEGER, INTENT(OUT) ::n !size of matrix to be read
COMPLEX, DIMENSION(:,:), INTENT(OUT), ALLOCATABLE ::A !system matrix to be read
COMPLEX, DIMENSION(:), INTENT(OUT), ALLOCATABLE ::b !RHS b vector to be read
DOUBLE PRECISION ::A_Re,A_Im,b_Re,b_Im !
INTEGER ::i,j
!----------------------------------------------------------
! Subroutine outputs 'n'=size of matrix, 'A'=system matrix
! 'b'= RHS vector
!matrix194.txt
OPEN (UNIT = 24, FILE = "matrix_input_test.txt", STATUS="OLD", FORM="FORMATTED", ACTION="READ")
!Read in size of matrix
READ(24,*) n
ALLOCATE(A(n,n))
ALLOCATE(b(n))
!Read matrix A:
DO i=1,n
DO j=1,n
READ(24,*) A_Re, A_Im
A(i,j)=CMPLX(A_Re,A_Im)
END DO
END DO
!Read RHS vector b:
DO i=((n*n)+1),((n*n)+n)
READ(24,*) b_Re, b_Im
b(i)=CMPLX(b_Re,b_Im)
END DO
CLOSE(UNIT=24)
DEALLOCATE(A,b)
END SUBROUTINE matrix_input
EDIT: Following HPC Mark's insights, I have edited my code, and this yields the correct result, however if there are any commands which could lead to issues later on down the line (e.g. with very large arrays that I will be using) I would very grateful to hear about them!
SUBROUTINE matrix_input(n,A,b)
IMPLICIT NONE
!
INTEGER, INTENT(OUT) ::n !size of matrix to be read
COMPLEX, DIMENSION(:,:), INTENT(OUT), ALLOCATABLE ::A !system matrix to be read
COMPLEX, DIMENSION(:), INTENT(OUT), ALLOCATABLE ::b !RHS b vector to be read
!
COMPLEX, DIMENSION(:), ALLOCATABLE ::temp,A_temp !temp vector of matrix A
DOUBLE PRECISION ::A_Re,A_Im,b_Re,b_Im
INTEGER ::i,j,k
!----------------------------------------------------------
! Subroutine outputs 'n'=size of matrix, 'A'=system matrix
! 'b'= RHS vector
!matrix194.txt
OPEN (UNIT = 24, FILE = "matrix_input_test.txt", STATUS="OLD", FORM="FORMATTED", ACTION="READ")
!Read in size of matrix
READ(24,*) n
!Allocate arrays/vectors
ALLOCATE(A(n,n))
ALLOCATE(b(n))
ALLOCATE(temp(n*n+n))
ALLOCATE(A_temp(n*n))
!Read matrix A & vector b:
!16 characters, 9 decimal places, exponent notation, 2 spaces
DO i=1,(n*n)+n
READ(24, FMT="(E16.9, 2X, E16.9)") A_Re, A_Im
temp(i)=CMPLX(A_Re,A_Im)
END DO
!Select A:
DO i=1,n*n
A_temp(i)=temp(i)
END DO
!Reshape
A=RESHAPE(A_temp, (/n,n/))
!Select b:
k=0
DO i=n*n+1,n*n+n
k=k+1
b(k)=temp(i)
END DO
CLOSE(UNIT=24)
!Do not deallocate A & b otherwise won't return anything properly
DEALLOCATE(temp, A_temp)
END SUBROUTINE matrix_input
RESULTS FROM THE EDITED CODE:
n= 2
A= (-0.73419207 , 7.1148620 ) ( 0.27449295 , 3.7885537 ) ( 0.24839121 , 4.1215405 ) (-0.63255787 , 1.9539773 )
b= ( 0.28961974 , 0.89556217 ) (-0.28475615 ,-0.89216310 )
High Performance Mark has already identified the significant issue, some other notes...
Your format specification in your updated code suggests two spaces in between numbers. Your example input suggests one - be mindful of the (optional) leading sign on the second number!
A and b are allocatable dummy arguments. That's a widely supported and very useful Fortran 2003 feature. You are well beyond Fortran 90! If that is unintentional then you will need to seriously redesign things, otherwise...
Being beyond Fortran 90 is a good thing - Fortran 95 (which is the minimum level of standard support offered by all current mainstream Fortran compilers - Fortran 90 is practically obsolete) and Fortran 2003 by extension fixed a serious deficiency in Fortran 90 - as of Fortran 95 local allocatable objects are deallocated automatically when the return or end statement of a procedure is executed. Your deallocate statement at the end is therefore harmless but redundant.
You read in the components of each complex number into double precision (note a common source code style used for modern Fortran tends to avoid the DOUBLE PRECISION type specifier - it is just a synonym for REAL(KIND(0.0D0))). You then store them into default (single precision) complex. Is that intentional? If so, its harmless but a little pointless/inconsistent, otherwise if you intended for the real and imaginary components in the output arrays to be stored at higher precision, then you need to change the declaration of the complex arrays appropriately. All kinds available for REAL must be available for COMPLEX, so your declaration could be COMPLEX(KIND(0.0D0)) (typically you would have the kind as a named constant).
In an input-output list, a complex scalar variable represents two effective items - the real part followed by the imaginary part. Consequently your double precision variables A_Re and A_Im, etc., are somewhat superfluous... READ(24, FMT="(E16.9, 2X, E16.9)") temp(i) is all that is required.
Personally I wouldn't bother with the other temporary arrays - once you know the size of the input data (the first line) allocate your A and B arrays to the necessary size and read directly into them. In an io list an array is expanded into its elements in array element order (first subscript varies fastest) - which appears to be the way your file is arranged. You can combine this with what's known as format reversion to eliminate the need for loops.
Upon return from your subroutine the allocatable arrays "know" their shape - there's no need to return that information separately. Again, harmless but redundant.
Consequently - I think your entire subroutine could look something like:
! Read A and B in from a file that has... etc, etc...
! Assuming a module procedure, where the module already has IMPLICIT NONE.
SUBROUTINE matrix_input(A, b)
! Number of rows and columns of A, elements of B.
INTEGER :: n
! Our output data.
COMPLEX(KIND(0.0D0)), INTENT(OUT), ALLOCATABLE :: A(:,:), b(:)
! Number of the logical unit for IO. In F2008 this becomes a variable
! and you use the NEWUNIT specifier.
INTEGER, PARAMETER :: unit = 24
! The name of the file to read the data from.
CHARACTER(*), PARAMETER :: filename = "matrix_input_test.txt"
! Format for the array and vector component of the data.
CHARACTER(*), PARAMETER :: fmt = "(E16.9, 1X, E16.9)"
!*****************************************************************************
! Connect to the file for sequential formatted reading.
OPEN(unit, FILE=filename, STATUS='OLD', ACTION='READ')
READ (unit, *) n ! Get array dimension.
ALLOCATE(A(n,n), b(n)) ! Allocate result arrays.
READ (unit, fmt) A ! Read in A.
READ (unit, fmt) b ! Read in B.
CLOSE (unit) ! Clean up.
END SUBROUTINE matrix_input
Your code confuses me. SUBROUTINE matrix_input declares arrays A and b to be allocatable with intent(out). Just before the END SUBROUTINE statement you go right ahead and deallocate them. What do you expect the subroutine to return to the calling routine ?

Can Fortran read bytes directly from a binary file?

I have a binary file that I would like to read with Fortran. The problem is that it was not written by Fortran, so it doesn't have the record length indicators. So the usual unformatted Fortran read won't work.
I had a thought that I could be sneaky and read the file as a formatted file, byte-by-byte (or 4 bytes by 4 bytes, really) into a character array and then convert the contents of the characters into integers and floats via the transfer function or the dreaded equivalence statement. But this doesn't work: I try to read 4 bytes at a time and, according to the POS output from the inquire statement, the read skips over like 6000 bytes or so, and the character array gets loaded with junk.
So that's a no go. Is there some detail in this approach I am forgetting? Or is there just a fundamentally different and better way to do this in Fortran? (BTW, I also tried reading into an integer*1 array and a byte array. Even though these codes would compile, when it came to the read statement, the code crashed.)
Yes.
Fortran 2003 introduced stream access into the language. Prior to this most processors supported something equivalent as an extension, perhaps called "binary" or similar.
Unformatted stream access imposes no record structure on the file. As an example, to read data from the file that corresponds to a single int in the companion C processor (if any) for a particular Fortran processor:
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT
INTEGER, PARAMETER :: unit = 10
CHARACTER(*), PARAMETER :: filename = 'name of your file'
INTEGER(C_INT) :: data
!***
OPEN(unit, filename, ACCESS='STREAM', FORM='UNFORMATTED')
READ (unit) data
CLOSE(unit)
PRINT "('data was ',I0)", data
You may still have issues with endianess and data type size, but those aspects are language independent.
If you are writing to a language standard prior to Fortran 2003 then unformatted direct access reading into a suitable integer variable may work - it is Fortran processor specific but works for many of the current processors.

maximum 'string' length in fortran

does fortran have a maximum 'string' length?
i am going to be reading lines from a file which could have very long lines. the one i am looking at now has around 1.3k characters per line, but it is possible that they may have much more. i am reading each line from the file to a character*5000 variable, but if i get more in the future, is it bad to make it a character*5000000 variable? is there a max? is there a better way to solve this problem than making a very large character variables?
Since the usual Fortran IO is record based, reading lines into strings implies knowing the maximum string length. Another possible design: use stream IO and Fortran will ignore the record boundaries. Read the file in fixed-length chunks that are shorter than the longest lines. The complication is handling items split across chunk boundaries. The practicality depends on details not given in the question.
P.S. From "The Fortran 2003 Handbook" by Adams et al.: "The maximum length permitted for character strings is processor-dependent." -- meaning compiler dependent.
Maximum wil be implementation dependant. For your case, I can think of something along these lines:
character(:),allocatable :: ch
l = 5
do
allocate(character(l) :: ch)
read(unit,'(a)',iostat=io) ch
if (ch(l-4:l) = ' ' .or. io/=0) exit
deallocate(ch)
l = l * 2
end do
Obviously will not work for pad='no' and if you expect long regions with spacec in your records.