Using Do-Loops in Include Files - fortran

In my fortran code, I'm attempting to include a DO loop, but I'm ending up with a "DO loop or BLOCK IF not closed." It appears if any other DO loops after the INCLUDE statement are opened it treats them as nested loops, indicating to me the included opening DO line is interpreted correctly, but not the END DO statement. I've reduced the included code to bare-bones to make sure it's the loop and not the statements in the loop giving a problem. The control variable is declared before the DO loop.
DO A = 1,3
END DO
Does Fortran77 not allow for DO loops in INCLUDE files?
I'm using gfortran for my compiler if it changes much.
Edit: grammar
Edit2:
I'm using GCC 4.6.2. Now to note, if this makes a difference, gfortran is being run from a makefile made by PSCAD. I can provide info on that if it's pertinent.
Here's code that is experiencing this issue:
TEST.F:
SUBROUTINE TESTFX()
INTEGER A
INCLUDE '../HDR.INC'
END
HDR.INC:
DO A = 1,3
END DO
Edit3: Edited typos in code and removed RETURN from subroutine.

Fortran 77 doesn't have INCLUDE at all. That first made its appearance in a Fortran standard in Fortran 90. That said, INCLUDE was available as an extension in pretty much all Fortran 77 compilers and the behavior was the same - it is essentially the same as inserting the included file in the source file where the INCLUDE appears. There are no restrictions on what can be there, though I have seen compilers struggle with issues related to block constructs that straddle an include file boundary.
Perhaps if you included both the source file and the include file text and told us exactly which version of gfortran you're using, a more definitive response could be provided.

Your INCLUDE must be placed on a new line, it is not part of the statement declaring A. Why do you have apostrophes at your ENDs? They cannot be there. The RETURN statement before the END is totally superfluous also. Try:
TEST.F:
SUBROUTINE TESTFX()
INTEGER A
INCLUDE '../HDR.INC'
END SUBROUTINE
HDR.INC:
DO A = 1,3
END DO

Related

Preserving line numbers when pre-processing Fortran code

I have inherited a 10K-lines Fortran code that uses fpx3 for pre-processing. At this point I should say that I don't have much Fortran experience, and this is my first time dealing with a code that has a pre-processor.
The code works fine, except that when the pre-processing runs, it creates secondary Fortran files (e.g., main.f90 creates t.main.f90) that do not preserve the total amount of lines. The reason, of course, is that some code is lost when pre-processing (IF-ELSE clauses, pre-proc. directives, etc.).
This would be fine, except that when I get a bug in the code, the line number I get from the bug refers to the pre-compiled code (e.g., t.main.90) instead of the original code.
This isn't a major problem, but for nearly every bug I have to check the line (say, line 80 of t.main.f90) and manually try to find this line in the original (let's say it ends up being line 92 of main.f90). I've tried to find a way around this by telling fpx3 to comment the unused lines instead of throwing them out, but I couldn't find much info on fpx3 online.
What's the best way around this?
P.S.: I don't know if it matters, but I'm using ifort to compile.
Try -fixed as a .f90 file is assumed to be -free (free form), and fixed preserves the 1st few columns and the continuation in column 6.
If the number at on the right hand side, then NOT -132, but -72 or -80. To not include the numbers as "compilable" code. I use -132, so you have to look up the right switch.

`Unexpected element ‘\’ in format string` in code written for MS Fortran [duplicate]

I have a project written in VS2010 with Intel Visual Fortran. I have a dump subroutine to write a 2D matrix into file:
subroutine Dump2D(Name,Nx,Ny,Res)
implicit none
integer i,j,Nx,Ny
real(8) :: Res(Nx,Ny)
character(len=30) name,Filename
logical alive
write(filename,*) trim(Name),".dat"
Write(*,*) "Saving ",trim(Name)," Please wait..."
open (10,file=filename)
do i=1,Ny
Write(10,FMt="(D21.13\)") (Res(j,i),j=1,Nx)
Write(10,*)
end do
close(10)
Write(*,*) "Save ",trim(Name),"Complete!"
return
end subroutine Dump2D
It is ok to compile and run. But when I compile in emacs using gfortran it gives me the error:
I think it's because the gfortran doesn't recognize \ in a format for a write command. How do I fix this problem?
Write(10,FMt="(D21.13\)") (Res(j,i),j=1,Nx)
1
Error: Unexpected element '\' in format string at (1)
The edit descriptor \ relates to backslash editing. This is a non-standard extension provided by the Intel compiler (and perhaps others). It is not supported by gfortran.
Such backslash editing is intended to affect carriage control. Much as in this answer such an effect can be handled with the (standard) non-advancing output.1
As you simply want to output each column of a matrix to a record/line you needn't bother with this effort.2 Instead (as you'll see in many other questions):
do i=1,Ny
write(10,fmt="(*(D21.13))") Res(:,i)
end do
There are also other approaches which a more general search will find.
1 The Intel compiler treats \ and $ in the same way.
2 There are subtle aspects of \, but I'll assume you don't care about those.
Another approach (although francescalus answer is better in your case) would be to build a format string that contains the number of elements to include in your row. One way of doing this is to use the following to build the format string (which uses an explicit space character to separate elements within a line in the file):
WRITE(fmtString, '(A,I0,A)') '(', Nx, '(D21.13,:,1X))' *
Then use the format string variable in your WRITE statement as so:
do i=1,Ny
Write(10,FMt=fmtString) (Res(j,i),j=1,Nx)
end do
This approach can also be very useful if you want to use something other than spaces to separate elements (e.g. commas or semicolons).
*As that's a little difficult to read, I will provide an example. For Nx = 3, this would be equivalent to:
fmtString = '(3(D21.13,:,1X))'
Which is 2 numbers formatted using D21.13, each followed by a space, and a final number formatted using D21.13, but without a space after it (as the ":" stops at the final item).
The backslash is not valid in Fortran 77 FORMAT statements. Gfortran will not compile it, unless you fix the code. There is no flag that will change that AFAIK (-fbackslash should not help here).
If I understand the intention correctly (and I may be wrong), the backslash does the same as the dollar sign in some other compilers and prevents terminating a record (line). In that case the advance="no" put in the write statement should help. It is Fortran 90, but you should not avoid it just for that reason.

Old FORTRAN Namelist Compiler (gfortran) Flag?

I'm currently in the process of upgrading an old program written in FORTRAN and I'm trying to get it to compile using gfortran. I can get it to build, however the program now chokes on the namelists that it is reading in.
An example of a namelist that came with the program is shown below. It cannot correctly read this file due to the space between the variable name and the parenthesis. Since these files are very large, is there anyway I can tell gfortran to expect an older namelist format?
&<NAME>
<VARNAME> (1) = 0,
<VARNAME> (2) = -1e-13,
<VARNAME> (3) = 0.2983
&End
If not, I can resort to doing a search/replace but I'd rather not mess with the data and just have the code successfully read it in.
Namelist is quite complicated, as you can tell from the fact that there are 92 namelist test cases in the gfortran testsuite.
gfortran has no option to do what you ask. You will probably have to remove the blanks by hand or by sed, like Vladimir F suggested.
I might add that blanks in the subobject designator (the varname(i) part) are explicitly forbidden in the F2003 standard 10.10.1.1:
"In the input record, each object name or subobject designator may be preceded and followed by one or more optional blanks but shall not contain embedded blanks."
so this is unlikely to be changed in a future version of gfortran.

Is there a way to include data in code file in Fortran?

My Fortran code needs to read a initialize data (about 24000 real numbers) from a file. Are there any ways to put the data in the code so that I can avoid accessing the filesystem?
I tried to use a module and put all the data into a variable initialization like this:
real(kind=8) :: a(24000)=(/&
& 1. ,&
& 2. ,&
...
&/)
but because of there are 24000 lines for the source file, I keep receiving compiling error "Too many continuation lines". Are there any solution to this?
You can use DATA statements for this.
The fact that you can "slice" up your array into sections (such as setting a[1..100] in one section, a[101..200] in the next and so on) means that you should be able to avoid the massive-statement-size problem you're experiencing.
For such a large amount of data I would use some script language (or even Fortran) to generate a chunk of simple Fortran code like
a(1) = ..
a(2) = ..
a(3) = ..
This code could be then copy-pasted or include-d into your source code.
One option may be to instruct your compiler to allow unlimited line lengths
and put the whole darn thing on one line.
gfortran -ffree-line-length-none
I've verified this works. I've got a 2Mb source file with just 3 lines
real(kind=8) :: a(24000)=(/ ......... /)
write(*,*)a(24000)
end
I wouldn't be surprised if some compiler has a practical line length limit though.
By the way gfortran does not like using a big data statement.
No error it just hangs (or takes a very long time )
//
Imagine that, my big data version actually compiled (and runs fine ) after 1.5 hours. Why data is handled by the compiler so vastly differently from an initialization assignment is a good question.
As the previous author stated you can use the data statement, but it can be time consuming to enter it into the code manually. Is there a reason that you are apprehensive about the use of a READ statement in a do loop to read in the file? If you can provide us with any input on the data file format we can better help you.
It might seem to be archaic, but you could use INCLUDE. You'd need to modify your data file to have the form you gave,
real(8), dimension(24000) :: a=(/1.0,2.0,...24000./)
and then include it in the main program as such:
program main
implicit none
include "my_data_file.for"
< ... >
end program main
You won't need to change your compilation command, your Fortran compiler will import the included file on its own--so long as the included file is in the same directory.

PGI Fortran integer format

I have an input text file that contains an integer record like:
1
which is read in Fortran code as:
read(iunit,'(i4)') int_var
which works fine with Gfortran, but the same code compiled with PGI Fortran Compiler expects a field 4 characters wide (the actual record is just 1 character) and throws an error. Now I know that the format specifies the width and this may or may not be correct behavior according to the Fortran standard, but my question is - is there a compiler option for PGI that would make it behave like Gfortran in this respect?
This 3rd party code I'm using has a lot (hundreds or thousands) of read statements like this and input data has a lot of records with "wrong" width so both modifying the code or the input data would require significant effort.
I don't think this is connected to blank. This read should not cause an error, unless you opened the file iunit with pad="no". Default is allways pad="yes", which causes the input record to be padded with blanks, if it is too short.
Are you sure, that you use correct input files, with correct line ends? There could be problems with text file that originate in Windows and in Unix the CR could be read in the input record. In this case using the unix2dos utility might help. You may try to read a character(4) string using the a4 edit descriptor to test for this.
Does PGI Fortran support the open keyword blank="null"? I think that this will change the read to the behavior that you want and minimize the modifications to the code. blank="null" versus blank="zero" doesn't seem to make a difference in gfortran 4.7.