2

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 
Mateus
  • 149
  • 7
  • 2
    Try `WRITE(*,'(4a12)') 'd','b','theta2','yinf/theta2'` and fiddle about with the `12` until you get output you like. For details, refer to *edit descriptors*. – High Performance Mark Jun 22 '18 at 20:16
  • Also, take a look into Fortran implied do in i/o routines for an elegant way of doing your input/output – Rodrigo Rodrigues Jun 22 '18 at 21:02
  • I didn't understand @RodrigoRodrigues – Mateus Jun 22 '18 at 21:08
  • 1
    Or to left justify, try `WRITE(*,'(t2,a,t28,a,t54,a,t80,a)') 'd','b','theta2','yinf/theta2'` This assumes all write (12,*) real(8) have 26 character spacings. – johncampbell Jun 22 '18 at 23:54
  • Nothing fancy, just a general tip on coding. I thought maybe OP doesn't know they can have an implied-do in their write/read statements, to make them like `read(10,*) (bb(i),cc(i),l0,yinf(i),l2,l3, i = 1, Nloop)`. Also, as a general tip, don't rely on hardcoded kind numbers like `real(8)` as it is not portable (see https://stackoverflow.com/questions/3170239/fortran-integer4-vs-integer4-vs-integerkind-4) – Rodrigo Rodrigues Jun 23 '18 at 00:05
  • Welcome at Stack Overflow. Be sure totake the [tour]. Note that `real(8)` is ugly and non-portable and does not always mean 8 bytes. – Vladimir F Героям слава Jun 23 '18 at 15:00
  • @Rodrigo Rodrigues, You example implies only 1 record could be provided, while the OP's DO implies at least Nloop records. Your example could also read Nloop records. Unfortunately, for the case where extra information was in each record in the file, your example would fail. read (lu,*) will read an unknown number of records (lines) until all required information has been recovered, which can cause problems with missing data fields. – johncampbell Jun 24 '18 at 03:19

1 Answers1

0

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
Rodrigo Rodrigues
  • 7,545
  • 1
  • 24
  • 36
  • @Mateus so, did you apply this suggestion? Did this answer help you? If yes, you can mark this as "accepted", so it'll be easier for other people with the same issue to find the solution. – Rodrigo Rodrigues Jul 13 '18 at 21:43