Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29244 Discussions

Writing to existing ASCII file with recl using ifx giving different result than gfortran

DrBob87
Beginner
724 Views

I have a program that generates an ASCII file containing numerous plot states, but it won't know how many total until it finishes. To facilitate post-processing, I want the first line of the file to contain the number of plot states. My solution for this has been to write a place holder on the first (or second) line during the first creation of the file, then close the file, and then reopen it using the following options:

open(unit=1, file=ofile, iostat=iost, status="old", action="write", access="direct", recl=reclength, form='formatted')

The trick here is ensuring the value of reclength is set appropriately. Initially I wanted to put the name of the variable being read on line 1 and then the value on line 2, but this made getting the reclength consistently correct for both DOS and Linux OS's much more tedious, so I opted to put the value being overwritten on line 1 and the name on line 2. Simple enough. 

This all worked fine in gfortran on both Linux and DOS.

I recently began working on compiling the program with ifx, though, and now I have encountered some confusing behavior. I have reduced this down to a toy problem, which contains two separate types of write statements that both produce different results from gfortran when compiled with ifx. Here's the toy program:

program ifx_write_first_line_test

implicit none

! Parameters
character(*), parameter :: ofile="out.txt"

! Integers
integer :: u, iost, reclength

! Create Output File
open(newunit=u, file=ofile, iostat=iost, status="replace", action="write")
write(u, '(A)') repeat(' ',23) // '1'
write(u, '(A)') repeat(' ',23) // '2'
write(u, '(A)') repeat(' ',23) // '3'
close(u)

! Get Record Length Of Output File
inquire(iolength=reclength) repeat(' ',24)

! Modify Output File
open(newunit=u, file=ofile, iostat=iost, status="old",  &
&    action="write", access="direct", recl=reclength,   &
&    form='formatted')

! Write-Version-1
write(u, '(I0)',  rec=1) 1
! Write-Version-2
!write(u, '(I24)',  rec=1) 1

close(u)

end program ifx_write_first_line_test

I then compile it in gfortran via the following:

gfortran -std=f2018 toy.f90

This produces an out.txt file containing the following:

1
                       2
                       3

Now, compiling it with ifx via the following:

ifx -warn all -std18 ifx_write_first_line_test.f90

produces an out.txt file containing the following:

1                      1
                       2
                       3

Then, if I comment out line 27 in my toy program, and uncomment line 29 (so changing from what I refer to as Write-Version-1 to Write-Version-2), I get even greater disagreement between compilers. 

With Write-Version-2, compiling with gfortran produces an out.txt file containing the following:

                       1
                       2
                       3

Compiling with ifx and then trying to run the resulting a.out file produces the following error:

$ ./a.out
forrtl: severe (66): output statement overflows record, unit -129, file /home/me/toy/ifx_write_first_line_test/out.txt
Image              PC                Routine            Line        Source
a.out              000000000041A147  Unknown               Unknown  Unknown
a.out              00000000004187AE  Unknown               Unknown  Unknown
a.out              0000000000405609  Unknown               Unknown  Unknown
a.out              000000000040516D  Unknown               Unknown  Unknown
libc.so.6          00007F256DA06D90  Unknown               Unknown  Unknown
libc.so.6          00007F256DA06E40  __libc_start_main     Unknown  Unknown
a.out              0000000000405085  Unknown               Unknown  Unknown

In summary then, for Write-Version-1 (which overwrites a record of length 24 spaces with '(I0)' format), the behavior differences are not a huge problem, but I'm not sure which is actually "correct" Fortran. The ifx approach is helpful because it only overwrites what the integer would fill, but the way gfortran also kind of makes sense in that it overwrites the entire record. It would, however, obviously be better if they produced consistent results. 

For Write-Version-2, though, the results from gfortran are what I would expect and the error from ifx signifies a serious problem. While I have found a couple bugs in compilers over the years, I'm still very aware this could very well be a problem with my source code so any feedback is greatly appreciated.

FYI, I'm running this on Windows 11 in WSL2 with the following compilers:

ifx: ifx version 2025.0.0

gfortran: GNU Fortran (Homebrew GCC 13.2.0) 13.2.0

This is my first time posting here so I hope this is clear enough, but please let me know if you need anything further. Thanks in advance for any help.

1 Solution
andrew_4619
Honored Contributor III
650 Views

You create the file as a sequential access file and then open it as a direct access file. In general this will fail as the formatting of the files with end of record markers etc can be different and will depend on the compiler implementation.

 

I would suggest either dump the adding the record count idea and if necessary read the file to get the number of records (read ubntil EOF) and then  rewind and process it.....

OR

Write a temp file. Create the  output file and add the number of records then append the tmp file. 

 

 

 

View solution in original post

3 Replies
andrew_4619
Honored Contributor III
651 Views

You create the file as a sequential access file and then open it as a direct access file. In general this will fail as the formatting of the files with end of record markers etc can be different and will depend on the compiler implementation.

 

I would suggest either dump the adding the record count idea and if necessary read the file to get the number of records (read ubntil EOF) and then  rewind and process it.....

OR

Write a temp file. Create the  output file and add the number of records then append the tmp file. 

 

 

 

DrBob87
Beginner
578 Views

I'm going to respectfully push back on your proposed solution andrew_4619.

I realize the end-of-line/carriage-return indicator(s) can vary, as I noted in my original post, which is precisely why I opted to use line 1 instead of line 2 to store this value. Doing so permits me to create a record length that should only include the data of line 1 minus any end-of-line characters. And this worked flawlessly in gfortran on Linux and DOS systems. 

I also haven't found anything (not saying it doesn't exist) that indicates you cannot open a sequential access file as direct access. In fact, in most of my Fortran references it seems this is part of the purpose of the recl parameter in the open() statement. Plus, I showed that it does actually work in ifx if you write with an '(I0)' format, so it does not appear there's anything inherently wrong with opening a sequential file as direct (again, that seems to be the point of the recl parameter). 

So, bottom line is, if my provided recl does not intrude past the end of the first line, then why should ifx crash when it tries to write to that record? Is ifx appending an end-of-line character to my Write-Version-2 example and thus making it overflow? Why would it append it there and not also in my Write-Version-1 example? 

0 Kudos
andrew_4619
Honored Contributor III
567 Views

I am going to push back your push back.... Fortran is a language governed by published standards which have a whole load of definitions, rules and constraints. The IO operations you are using open/write etc are functions within the RTL (run time libraries).
In opening a file with attributes that are incompatible with the files creation your program is non-conforming. Whilst you might successfully reverse engineer the different file formats the rules of the standard allow the processor (i.e. compiler) a degree of latitude and in such cases they may legitimately behave the same or differently with some aspects. I do not think you have meaningfully demonstrated a bug and I do not think any of the Intel support people will be much interested. Why not just spend 10 minutes making a conforming program and stop trying to make cludgy workarounds?

Reply