PROBLEM : Long list of directives openmp fortran77
c$omp parallel default(shared) private(i,k,i1,i2,i3,i4,i5,
$ i6,x0,y0,z0,vnx0,vny0,vnz0,qs0)
c$omp do
Task to be performed
c$omp end do
c$omp end parallel
I'm trying to compile the above program using ifort and it works fine. I have checked with the serial version and I get the same result
ifort -openmp -parallel -o ./solve
But when I try to compile using gfortran it doesn't work.
gfortran -fopenmp
I get the following error
quinckedrop.f:2341.57:
*$omp parallel default(shared) private(i,k,i1,i2,i3,i4,i5
1
Error: Syntax error in OpenMP variable list at (1)
quinckedrop.f:2342.6:
$ ,i6,x0,y0,z0,vnx0,vny0,vnz0,qs0)
1
Error: Bad continuation line at (1)
quinckedrop.f:2342.15:
$ ,i6,x0,y0,z0,vnx0,vny0,vnz0,qs0)
1
Error: Invalid character in name at (1)
quinckedrop.f:2381.72:
*$omp end parallel
1
Error: Unexpected !$OMP END PARALLEL statement at (1)
quinckedrop.f:2768.6:
$ private(i,k,i1,i2,i3,i4,i5,i6,x0,y0,z0,vnx0,vny0,vnz0)
1
Error: Bad continuation line at (1)
quinckedrop.f:2768.21:
$ private(i,k,i1,i2,i3,i4,i5,i6,x0,y0,z0,vnx0,vny0,vnz0)
1
Error: PRIVATE statement at (1) is only allowed in the specification part of a module
quinckedrop.f:4302.6:
$ private(i,k,i1,i2,i3,i4,i5,i6,x0,y0,z0)
1
Error: Bad continuation line at (1)
quinckedrop.f:4302.21:
$ private(i,k,i1,i2,i3,i4,i5,i6,x0,y0,z0)
1
Error: PRIVATE statement at (1) is only allowed in the specification part of a module
quinckedrop.f:5738.6:
$ private(i,k,i1,i2,i3,i4,i5,i6,x0,y0,z0
1
Error: Bad continuation line at (1)
quinckedrop.f:5738.21:
$ private(i,k,i1,i2,i3,i4,i5,i6,x0,y0,z0
1
Error: PRIVATE statement at (1) is only allowed in the specification part of a module
This proposed solution doesn't work for me (may be because I am using fortran77)
Your problem simply boils down to that the OpenMP continuation syntax for fixed format sources Fortran code is like this:
c$omp parallel blah
c$omp+private( blah )
c$omp+reduction( blah )
Well, to be more precise, all the 3 following forms for directives are equivalent:
c$omp
!$omp
*$omp
But in any case, a directive spread across several lines must be split using an extra character in the 6th column, as already shown. This character can be anything but a space or a zero. (thanks to Hristo Iliev for having corrected me in that. Initially mistakenly stated that the continuation character was supposed to be a +)
Adding the various necessary c$omp+ continuation lines should just solve your problem
This should look like this:
c$omp parallel default(shared) private(i,k,i1,i2,i3,i4,i5,
c$omp+ i6,x0,y0,z0,vnx0,vny0,vnz0,qs0)
c$omp do
Task to be performed
c$omp end do
c$omp end parallel
Related
This question already has answers here:
OpenMP Several "shared"-directives?
(2 answers)
Closed 2 years ago.
I have a line of a Fortran code, e.g.,
!$omp do private(aa, bb, cc) schedule(dynamic) reduction(+:alpha, beta, gamma)
Suppose this line contains several arguments and the length exceeds 132 characters, gfortran will lead to error message. I tried to use & to break the line. But I am not sure how to start the next line. As other case, directly start the next line without ! leads to Error: Syntax error in OpenMP variable list at (1).
How to break the 132 characters limit for omp line?
You can write multiline omp statements by ending with & and staring a newline with $omp.
Example
!$omp do private(aa, bb, cc) &
!$omp schedule(dynamic) &
!$omp reduction(+:alpha, beta, gamma)
...
!$omp end do
I am trying to put newlines inside a preprocessor macro.
One reason I want this is to deallocate a number of variables, but first check to make sure they were allocated. If they're not allocated, then there should be a useful error. In this example:
$ cat main.F90
program main
implicit none
integer :: n = 10
integer, allocatable, dimension(:) :: x, y
allocate(x(n))
#define check_deallocate(QQQ) \
if (.not. allocated(QQQ)) then \
write(*,*) '** Error, QQQ is not allocated' \
error stop \
else \
deallocate(QQQ) \
endif
check_deallocate(x)
check_deallocate(y)
end program
For this code, I get the following:
$ gfortran -E main.F90 #-E outputs the preprocessed source
...
if (.not. allocated(x)) then write(*,*) '** Error, x is not allocated' error stop else deallocate(x) endif
if (.not. allocated(y)) then write(*,*) '** Error, y is not allocated' error stop else deallocate(y) endif
...
Obviously, this is undesirable because the 132 character limit is not respected. Hence my question: what is the syntax to include a newline in the preprocessed source code?
Here are some things I have found that do not quite answer my question
This question was asked for C++ here, but it doesn't appear to work for fortran.
I do not want to define another macro (such as ___CR__) and use sed or some other utility to replace it with \n. I would like the solution to exist within 'typical' preprocessors (eg. ifort and gfortran).
If what I'm asking for is not possible, that's an answer to my question also. Also, I'm somewhat aware of the lack of standardization in fortran preprocessors, but I'm still asking for a relatively generic solution.
It's not possible on its own, but if you're allowed to use a separated preprocess step, you could do it with the following:
SUFFIXES:
.SUFFIXES: .f90 .o
.f90.o:
fpp -P $/n/g' > $*.ftn
ifort -free -c $*.ftn
(untested. I found this suggestion at this link)
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.
I am modifying a code from a model written in Fortran 77, but I have come across an odd thing to me. In some files, there is a label "d" in the first column of a line, like the example below:
d real*8 co2rootfix,co2rootloss,co2shootfix
d character komma*1
d open(unit=87,file='crop_CO2.csv',status='unknown')
d write(87,*) 'date,co2rootfix,co2rootloss,co2shootfix'
d open(unit=88,file='crop_dm.csv',status='unknown')
d write(88,*) 'date,wrtpot,wrt,wstpot,wst,rdpot,rd,laipot,lai,
d &gwrt,gwst,drrt,drlv,drst'
The weird thing is that it is successfully compiled by Intel's ifort compiler. However, gfortran logically returns the following error:
Error: Non-numeric character in statement label at (1)
I would like to know:
the meaning of this label;
why it is only recognized by ifort and;
how I can make it work with gfortran.
From the ifort documentation there are the options -d-lines and -nod-lines:
This option compiles debug statements. It specifies that lines in fixed-format files that contain a D in column 1 (debug statements) should be treated as source code.
So, if the code is compiled without -d-lines (or with -nod-lines which is the default) then those lines with d in the first column in treated as comments and ignored.
In gfortran -fd-lines-as-code and -fd-lines-as-comments have the same effect. The difference here is that ifort, as an extension, accepts the code regardless of flags (as above, it has the implicit -nod-lines). gfortran requires exactly one of the flags to be specified to accept the code.
I'm having a runtime error when I run a code that works without problems using a different computer.
I'm wondering if the problem is the Fortran compiler of this machine (GCC 4.9.2) since the former computer used a previous version.
The issue comes when defining a variable like this:
In a module I define
character(30),allocatable,save :: sceneclass(:)
Then in the subroutine sceneclass is defined according to
character(30) surf, frac, scene
allocate(sceneclass(10))
do i=1,10
write(sceneclass(i),*) trim(scene)//trim(surf)//'_'//trim(frac)
enddo
In the first iteration I get the "End of record". But I don't know where is the problem. It seems to work fine in other computers.
You are probably writing a string to sceneclass(i) that is longer then the 30 chars you specified.
I can reproduce this with
program test
implicit none
character(10),allocatable :: sceneclass(:)
integer :: i
allocate( sceneclass(10) )
do i=1,10
write(sceneclass(i),*) 10**i
enddo
print *, ( trim(sceneclass(i)), i=1,10 )
end program
gfortran fails with
Fortran runtime error: End of record
while ifort reports the error correctly:
output statement overflows record, unit -5, file Internal List-Directed Write
Increasing the string length to 12 solves the issue in this case. You can (and should) use iostat within the write statement to capture this.
One thing to be aware of, when you specify a list directed * write of a character string, the compiler always(?) adds an extra lead blank, so the effective length of the string you can write is one less than you might expect.
To remedy that (and of course assuming you don't want the lead blank anyway ) use a string edit descriptor:
write(sceneclass(i),'(a)')...
Interestingly ifort (linux 11.1) actually allows you to overrun by one character:
character*5 c
write(c,*)'12345' ! result: " 1234"
which I would consider a bug. It seems they forgot to count the blank too.. ( gfortran throws the above error on this, and ifort balks if you add one more character )
see here if you wonder why the blank.. Are Fortran control characters (carriage control) still implemented in compilers?
and now I'm curious if some compiler somewhere didn't do that for an internal list write, or maybe your code was previously compiled with a flag to disable the "printer control" code