FORTRAN operators on the left hand side - fortran

I'm compiling a G77/GNU FORTRAN code developed in Linux to work with Intel Fortran in Windows. I got a strange assignments in the code to modify the DO loop index such as I+1=M or I-1=N where I in the index of the DO loop. This is not accepted by Intel Fortran compiler. The modification of the loop index is also not allowed in Intel Fortran compiler. What are the equivalent code in Intel Fortran for these assignments?
The code is as follows:
DO L=2,LA
I=IL(L)
J=JL(L)
IF(IJCT(I-1,J).EQ.9)THEN
L-1=LC
ELSE
L-1=LIJ(I-1,J)
L-1=MAX(L-1,1)
ENDIF
IF(IJCT(I+1,J).EQ.9)THEN
L+1=LC
ELSE
L+1=LIJ(I+1,J)
L+1=MAX(L+1,1)
ENDIF
ENDDO

Related

How to tell if your Fortran program has been compiled with OpenMP or not?

I'm curious as to if there's a way to tell if your program has been compuled with -fopenmp or -xopenmp etc. and subsequently write something to the screen saying, "OpenMP being used etc..." or if it has been complied without -fopenmp or -xopenmp write "OpenMP not being used..."
Is there a flag that can be used to tell if the program has been compiled with OpenMP or compiled without so I could write something within my program like I've briefly written below?
program main
use omp_lib
implicit none
!define other variables here...
logical :: complied_with_openmp
if(complied_with_openmp .eqv. .true.) write(6,*) 'OpenMP used...'
if(complied_with_openmp .eqv. .false.) write(6,*) 'Openmp not used...'
!some other code here...
end program
Your question is quite strange. Don't you actually want to ask if you are compiling with OpenMP right now? That can be done by using the !$ syntax. Statements after !$ are only compiled with OpenMP.
logical :: compiled_with_openmp = .false.
!$ compiled_with_openmp = .true.
if (compiled_with_openmp) then
write(*,*) 'OpenMP used...'
else
write(*,*) 'Openmp not used...'
end if
Also, don't use unit 6, use *, it is more portable and nicer.
And do not compare logicals with .true. or .false., just do if (condition), doing if (condition .eqv. .true.) is superficial or even confusing. And if the two conditions are actually opposite, just use if else to join them.
If you have a Fortran 2008 compliant compiler you can use the intrinsic function compiler_options to find out what compiler options were used; it's in the intrinsic module iso_fortran_env. I imagine that compilers which don't (yet) provide this may have non-standard ways of determining what compiler options were used.
You could then use index to figure out if the compiler options include the flag to engage OpenMP. On my installation of gfortran the expression
index(compiler_options(),'openmp')
returns a non-0 value when the code is compiled with -fopenmp.
omp_lib provides the integer constant openmp_version to tell you what version you're using. To be more accurate, it returns an integer yyyymm which decodes to the year and month of the release of the OpenMP version, rather than a direct representation of the version, such as 4.5.

Allocatable arrays in fortran 77 and gfortran

I'm trying to compile some old fortran77 programs with gfortran and getting error with allocatable arrays.
If I define arrays in f90-style, like:
REAL*8,allocatable::somearray(:)
everything is fine, but in those old programs arrays defined as:
REAL*8 somearray[ALLOCATABLE](:)
which cause gfortran error output:
REAL*8,allocatable::somearray[ALLOCATABLE](:)
1
Fatal Error: Coarrays disabled at (1), use -fcoarray= to enable
I really wish to avoid rewriting whole programs to f90 style, so, could you please tell me, is there any way to force gfortran to compile it?
Thanks a lot.
For standard checking you can use -std flag
-std=std
Specify the standard to which the program is expected to conform, which may be one of f95',f2003', f2008',gnu', or `legacy'.
To "force" gfortran to compile your code, you have to use syntax it recognizes
I'd probably go for search and replace. For example,
sed 's/\(REAL\*8\)[[:blank:]]\+\([^[]\+\)\[ALLOCATABLE\]\(.*\)/\1, allocatable :: \2\3/' <old.source> > <new.source>
where sed is available.
Of course, be careful with sed :).
In any case, as it seems your code was written in some non-standard version of old
Fortran, you'll probably need to make changes in any case.
For what it's worth the Intel Fortran compiler (v13.something) compiles the following micro-program without complaint. This executes and writes 10 to the terminal:
REAL*8 somearray[ALLOCATABLE](:)
allocate(somearray(10))
print *, size(somearray)
end
Given the history of the Intel compiler I suspect that the strange declaration is an extension provided by DEC Fortran, possibly an early implementation of what was later standardised in Fortran 90.

Puzzling performance difference between ifort and gfortran

Recently, I read a post on Stack Overflow about finding integers that are perfect squares. As I wanted to play with this, I wrote the following small program:
PROGRAM PERFECT_SQUARE
IMPLICIT NONE
INTEGER*8 :: N, M, NTOT
LOGICAL :: IS_SQUARE
N=Z'D0B03602181'
WRITE(*,*) IS_SQUARE(N)
NTOT=0
DO N=1,1000000000
IF (IS_SQUARE(N)) THEN
NTOT=NTOT+1
END IF
END DO
WRITE(*,*) NTOT ! should find 31622 squares
END PROGRAM
LOGICAL FUNCTION IS_SQUARE(N)
IMPLICIT NONE
INTEGER*8 :: N, M
! check if negative
IF (N.LT.0) THEN
IS_SQUARE=.FALSE.
RETURN
END IF
! check if ending 4 bits belong to (0,1,4,9)
M=IAND(N,15)
IF (.NOT.(M.EQ.0 .OR. M.EQ.1 .OR. M.EQ.4 .OR. M.EQ.9)) THEN
IS_SQUARE=.FALSE.
RETURN
END IF
! try to find the nearest integer to sqrt(n)
M=DINT(SQRT(DBLE(N)))
IF (M**2.NE.N) THEN
IS_SQUARE=.FALSE.
RETURN
END IF
IS_SQUARE=.TRUE.
RETURN
END FUNCTION
When compiling with gfortran -O2, running time is 4.437 seconds, with -O3 it is 2.657 seconds. Then I thought that compiling with ifort -O2 could be faster since it might have a faster SQRT function, but it turned out running time was now 9.026 seconds, and with ifort -O3 the same. I tried to analyze it using Valgrind, and the Intel compiled program indeed uses many more instructions.
My question is why? Is there a way to find out where exactly the difference comes from?
EDITS:
gfortran version 4.6.2 and ifort version 12.0.2
times are obtained from running time ./a.out and is the real/user time (sys was always almost 0)
this is on Linux x86_64, both gfortran and ifort are 64-bit builds
ifort inlines everything, gfortran only at -O3, but the latter assembly code is simpler than that of ifort, which uses xmm registers a lot
fixed line of code, added NTOT=0 before loop, should fix issue with other gfortran versions
When the complex IF statement is removed, gfortran takes about 4 times as much time (10-11 seconds). This is to be expected since the statement approximately throws out about 75% of the numbers, avoiding to do the SQRT on them. On the other hand, ifort only uses slightly more time. My guess is that something goes wrong when ifort tries to optimize the IF statement.
EDIT2:
I tried with ifort version 12.1.2.273 it's much faster, so looks like they fixed that.
What compiler versions are you using?
Interestingly, it looks like a case where there is a performance regression from 11.1 to 12.0 -- e.g. for me, 11.1 (ifort -fast square.f90) takes 3.96s, and 12.0 (same options) took 13.3s.
gfortran (4.6.1) (-O3) is still faster (3.35s).
I have seen this kind of a regression before, although not quite as dramatic.
BTW, replacing the if statement with
is_square = any(m == [0, 1, 4, 9])
if(.not. is_square) return
makes it run twice as fast with ifort 12.0, but slower in gfortran and ifort 11.1.
It looks like part of the problem is that 12.0 is overly aggressive in trying to vectorize things: adding
!DEC$ NOVECTOR
right before the DO loop (without changing anything else in the code) cuts the run time down to 4.0 sec.
Also, as a side benefit: if you have a multi-core CPU, try adding -parallel to the ifort command line :)

fortran compiler 4 vs 11

I am porting an application from fortran older version (4.0) to new version (11.0). While porting I am facing some problems with real*4 variables:
real*4 a,b,c
a=0.9876875
b=0.6754345
c=a*b
value for c in old compiler 0.667118, which is correct value. But with new compiler I am getting a small variation from the output(c variable) like 0.667120. Though it is a small variation, I am using these values in some other calculation. So the overall output has a huge difference. How to overcome this issue?
You are, I'm assuming, going from Microsoft Fortran Powerstation 4 to Intel Visual Fortran 11.xx ?
Anyways, try this:
program test32
integer, parameter :: iwp = selected_real_kind(15,300)
real(iwp) :: a,b,c
a=0.9876875
b=0.6754345
c=a*b
write(*,'(3f12.8)')a,b,c
end program test32
which gives out:
0.98768753 0.67543453 0.66711826
I will not explain selected_real_kind, not because I do not wish, but because the help will probably do it much better. But, do ask if something in here is not clear.
p.s. The representation of real*4, or any type of real is processor dependent, and compiler dependent and that is one of the reasons why you're getting different results.
Discussion of changes in Intel visual Fortran compiler version 11 here:
http://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/68587/
The upshot is that older versions of the Fortran compiler would implicitly promote single-precision values to double-precision before performing an operation. The default behavior in version 11 is to perform the operation with single-precision. There are compiler options (/arch:ia32) to enable the old behavior in the new compiler.
I assume you are using Intel. Try to compile without optimization..

How to identify fortran standard - '77, '90, or '95?

I have a piece of fortran code, and I am not sure which standard it is - '77, '90 or '95. Is there a standard tool to identify which standard it subjects to?
There probably are automated tools, but my methods are largely heuristic:
Do comments use a ! anywhere on the line (F90+) or a C in the first column (F77)?
Do loops use do..end do (F90+) or do..continue (F77)?
Are lines continued using & at the end of the line (F90+) or in column 6 (f77)?
Does the code use module or type structures (F90)?
If the code uses arrays, does it operate on them as a single structure (F90) or always using loops (F77)?
Is dynamic memory (either using allocatable or pointer methods) used (F90)?
Generally these are enough to discriminate between F90 and F77. The differences between Fortran 90 and FORTRAN 77 are much, much larger than the differences between Fortran 90 and Fortran 95 so I usually stop there.
If you have access to GNU Fortran (gfortran) you can try compiling it with the different options for --std and see which one works. You can find details on the dialect options here.
I'm adding features in fortran 2003 and 2008 (which are just back of my head)
if the program has parameterized-derived datatypes (fortran 2003.)
if the array constructor uses square brackets [ ] instead of (/ /) (fortran 2003.)
if you see,there is provision of using coarrays (fortran 2008)
although many compilers have special functions(like Bessel functions) as part of extensions , it is a bonafide fortran 2008 feature.
(if any discrepancies let me know i'll edit)