0

I'm very new to Fortran, and I'm trying to read and understand a lengthy code written in Fortran. I want to know what these lines mean/do.

do i=1, nbom_e
        temp = 0._SGL
        do j=1, pan_nu
            k = min(12, 2*nb_m)
            write(string,"('(1X, ES13.6, 1X, I2, 1X, I9, ',  I2, '(1X, ES13.6))')") k
            read(10,string, iostat=io) temp(1,j), dum1, dum2, temp(2:1+k,j)
            if (io/=0) write(*,*) 'Read failure', i, j, k
...

The code continues, but this is where it is difficult for me to understand - especially, the write(string... part.

I understand this is a rather simple question, and a simple Google search gave me some information about Format Specifiers. But I cannot understand the part completely, and I cannot move forward to implement this in another language without understanding it.

  • What documentation did the Google find? There is enough documentation that is really complete available. There are many questions about this broad topic at this very site as well. Good questions at this site concentrate on some specific problem, e.g. the meaning of a specific part of the format string, or of the iostat specifier only, or something else sufficiently specific. Requesting explanation of a code block sounds too broad to me. If you plan to translate significant amount of code from language A to language B you should invest some time to study language A. – Vladimir F Героям слава Mar 28 '23 at 08:19
  • Existing questions about format strings https://stackoverflow.com/questions/22350099/fortran-can-you-explain-this-formatting-string https://stackoverflow.com/questions/30306836/legacy-fortran-format-edit-descriptor-syntax-number-before-type https://stackoverflow.com/questions/24438611/fortran-format-1p10e11-3 https://stackoverflow.com/questions/22050804/fortran-format-what-does-the-symbol-1-mean If you do understand some part already, it would be good to specify that, so that the answerers do not have to explain everything that appears in those code lines. – Vladimir F Героям слава Mar 28 '23 at 08:22
  • Thank you. I'm sorry for posting a repeated question. – Jake Stravinsky Mar 28 '23 at 08:33
  • I do not think it is a repeated question. It is just a non-specific one. Also, there is nothing that bad in asking a repeated question, making no effort to specify it is worse. – Vladimir F Героям слава Mar 28 '23 at 08:36
  • For example, if I were to answer the question, I would have probably ignored the internal file thing and tried to explain all those individual `1X, ES13.6, 1X, I2, 1X, I9, ', I2, '(1X, ES13.6)` bits. Simply because I thought that was your problem. janneb's answer is about something different but there is nothing in the question that would tell that that is the thing you have a problem with. – Vladimir F Героям слава Mar 28 '23 at 08:43
  • This all that leads to you unaccepting an already accepted answer and accepting a different one, which can be pretty frustrating, sometimes, before it wasn't really well specified what actually should be answered. – Vladimir F Героям слава Mar 28 '23 at 09:29
  • Hi, Vladimir. I'm more than happy to provide some context for my question, although I don't think it's relevant. I'm dealing with some code written in Fortran to implement a theory that I'm working on. Years of my work are built on a different language, and learning the entire Fortran language is not time efficient, at least at the moment. I'm not arguing here, but I felt one answer explained what I needed better than the other. It was about clarifying a confusion "I" had, and thus, I accepted the answer that was posted later. I hope it is okay. I'll specify my questions better next time :) – Jake Stravinsky Mar 28 '23 at 09:51

2 Answers2

1

Assuming the string in write(string, ...) is a variable of type character, then this is what is called an "internal write". I.e. instead of writing to an external file (identified by an integer unit number) you're writing to a string. If you're familiar with C, this is somewhat equivalent to sprintf().

So what the code does in the write(string, ...) statement is that it's creating a format string dynamically, which is then used as a format string in the following read statement.

As for translating this particular code to another language, without an understanding of Fortran this is unlikely to be successful. Just looking at this very short snippet you provided, this looks like decent Fortran written in a somewhat modern style, so one wonders why the wheel has to be reinvented in another language, but I digress.

janneb
  • 36,249
  • 2
  • 81
  • 97
  • Thank you SO much, this makes a lot more sense now. So, the `"('(1X, ES13.6, 1X, I2, 1X, I9, ', I2, '(1X, ES13.6))')"` part is the formatting string. Is there a way to presume how many blocks/elements are read by this format? Am I right to assume that each comma separates the element? i.e., this string reads 9 elements in a line? Or am I completely wrong? – Jake Stravinsky Mar 28 '23 at 08:29
  • Sorry for asking a repeated question. This is clarified now. Thank you. – Jake Stravinsky Mar 28 '23 at 08:36
  • 1
    @JakeStravinsky: The parts of that format string inside ' ' are string literals (from the perspective of the write statement). The 'k' in the write applies to the unquoted I2 format specifier. E.g. if k=42, after the write the variable string would have the content "((1X, ES13.6, 1X, I2, 1X, I9, 42((1X, ES13.6)))" – janneb Mar 28 '23 at 08:36
1

The write(string,...) ... is way to write some data directly into a string instead of a into a file. The purpose here is to prepare the format needed for the read that follows.

Let's look first at what string contains for k=5 for instance: (1X, ES13.6, 1X, I2, 1X, I9, 5(1X, ES13.6))

string is used as a format for the read, which is (I am adding unit= and fmt= for clarity):

read(unit=10, fmt=string, iostat=io) temp(1,j), dum1, dum2, temp(2:1+k,j)

This means that the user wants to read data that is formatted like this in the file:

  • 1X: 1 leading space
  • ES13.6 a floating point number occupying 13 characters in scientific notation, 6 of them being the fractional part, e.g. 3.123456E+15
  • 1X: 1 space
  • I2: an integer number occupying 2 characters
  • 1X: 1 space
  • I9: an integer number occupying 9 characters
  • 5(1X, ES13.6): 5 consecutive floating point numbers in scientific notation, with a space before each of them

The way string is prepared by the write() is a bit difficult to read. It uses the fact that arbitrary strings can be put in fmt="...". Here are equivalent instructions that are maybe easier to read (the & is the line continuation symbol in Fortran):

write(string, fmt="(A,I2,A)") "(1X, ES13.6, 1X, I2, 1X, I9, " , &
                              k                               , &
                              "(1X, ES13.6))"

Or (// is the string concatenation operator)

write(string, fmt="(I2)") k
string = "(1X, ES13.6, 1X, I2, 1X, I9, " // &
         trim(string)                    // &
         "(1X, ES13.6))"
PierU
  • 1,391
  • 3
  • 15