While attempting to use fftw3 libraries in VS2008 with Intel Fortran, I encountered a problem with the data types defined by the iso_c_binding.
Considering that fftw3 defines in fftw3.f03:
integer, parameter :: C_FFTW_R2R_KIND = C_INT32_T
When compiling a code with the line
integer(C_FFTW_R2R_KIND), dimension(*), intent(in) :: kind
I get the following error:
error #6684: This is an incorrect value for a kind type parameter in this context. [C_FFTW_R2R_KIND]
To understand the problem, I tried the following code
program test
implicit none
call sub()
contains
subroutine sub()
use, intrinsic :: iso_c_binding
implicit none
write(*,*) C_INT, C_DOUBLE , C_INT32_T, C_INT_FAST32_T, C_INT_LEAST32_T
end subroutine sub
end program test
After running, the following result is displayed:
4 8 -2 -2 -2
As -2 is not a valid data type, I assumed that was the problem and looking in https://software.intel.com/en-us/node/678431, I replaced the line in fftw3.f03 by this:
integer, parameter :: C_FFTW_R2R_KIND = 4 !C_INT32_T
And I can run the program without errors.
If anybody could confirm that this alternative is correct or how to solve the original problem I would appreciate it.
Your approach will work fine for Intel Fortran, although using SELECTED_INT_KIND(8) instead of 4 would be safer and more portable.
Intel Visual Fortran apparently uses Visual C++ as a companion C compiler. And apparently a version that does not supports these C99 types yet. AFAIK Visual C++ is more oriented towards C++ than C and does not bring new C standard features too fast. They are supported in recent versions though https://msdn.microsoft.com/en-us/library/323b6b3k.aspx
In my opinion it would be more useful for Intel Fortran to define the c_ kind values anyway even if the C compiler does not define those constants, but maybe it is not completely standard conforming. But I think it would be a useful extension.
You simply need a newer version of Intel Fortran. If you are using VS2008, you would be at most using version 14; the current version is 18 and your test program there produces the result:
4 8 4 4 4
Related
I am trying to compile a fairly modern fortran code on a Mac with gfortran. Lines like this one ...
allocate(sce, mold=sct)
get errors like this:
Error: Array specification or array-valued SOURCE= expression required in ALLOCATE statement
It seems, then, that gfortran understands SOURCE but not MOLD. However, my gfortran is recent:
gcc version 8.2.0 (MacPorts gcc8 8.2.0_3)
I have seen web pages claiming that gfortran has been able to support MOLD since version 7.something. So surely it should be able to do it with 8.2.0. Is this not true? Is something funny about the Mac version? Can anyone suggest what some other problem might be?
EDIT: If anyone's still there, this toy code works fine:
program awm
integer, dimension(:), allocatable :: sct,sce
integer :: nspec = 100
allocate(sct(nspec))
allocate(sce, mold=sct)
end program
But when sct and sce are derived types, it falls apart:
program awm
type :: r1d
real, allocatable :: a(:)
end type
type(r1d), dimension(:), allocatable :: sct,sce
integer :: nspec = 100
allocate(sct(nspec))
do i = 1,nspec
allocate(sct(i)%a(10))
enddo
allocate(sce, mold=sct)
end program
This returns the error I was having above. You might think the definition of the derived type is kind of weird, even unnecessary. Well, the original code from which this is taken is not my code and I'm not in a position to change it much, and actually, this structuring does have its uses for reasons I don't have time to go into. Thanks.
I am convinced this is a duplicate of this GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80708 or is very closely related. You have to wait for a fix. I will put your code in the comment for this bug and not open a new one.
Is there a way within an Intel Visual Fortran project to get a string representing the Visual Studio Solution Directory?
Get_Environment_Variable doesn't seem to have that ability as far as I can tell.
Intel Fortran 2017 and VS 2015.
From your other comments, it seems to me that you're possibly more interested in the directory containing the executable. If you know your solution directory structure you can work out the solution location from that.
You do this in two steps. First you call the Windows API routine GetModuleHandle, passing NULL as the argument. This returns a handle to the current executable. Then you pass this handle to GetModuleFileName which returns the path to the executable as a NUL-terminated string.
If you wanted to separate out just the path, you could use the Intel library routine SPLITPATHQQ.
Example:
program whereami
use kernel32
use, intrinsic :: ISO_C_BINDING
implicit none
integer(HANDLE) :: h
character(MAX_PATH) :: f
integer(DWORD) :: ret
h = GetModuleHandle (NULL)
ret = GetModuleFileName (h,f,len(f))
print *, f(1:index(f,C_NULL_CHAR)-1)
end program whereami
Within the property pages for an Intel Fortran project you can use the $(SolutionDir) macro to query the solution directory.
There are a number of ways to then incorporate the value of this macro into Fortran source when it is compiled (e.g. define a preprocessor symbol on the compiler command line and then reference that preprocessor symbol in the source), or pass the value of that macro to a runtime instance of your program (e.g. through a command line argument, specified via the relevant project property) when the program is started from within Visual Studio.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am working on a custom CFD Solver written in Fortran 90 and MPI.
The code contain 15+ Modules and was initially designed to work with the Intel Fortran compiler. Now since i do not have access to the Intel compiler I need to make it work using the GNU Fortran Compiler.
I made changes in the Makefile that initially had flags suitable for the ifort.
I am using it on Ubuntu with GNU Fortran and Openmpi
I am sorry I am unable to put in anything from the code structure or terminal output due to IP restrictions of my university. Nevertheless,I will try to best describe the issues
So now when I compile the code I am having some strange issues.
The GNU Fortran is not able to read lines that are too long and I get errors during compilation. As a result I have to break it into multiple lines using the '&' symbol
A module D.f90 contains all the Global variables declared. However, now I during compilation i get error is in module B.F90.
The error I get is 'Unclassified Statement Error', I was able to fix it in some subroutines and functions by locally declaring the variables again.
I am not the most experienced person in Fortran, but I thought that the change in compiler should not be a reason for new found syntax errors.
The errors described above so far could be remedied but considering the expanse of the code it is impractical.
I was hoping if anyone could share views on this matter and provide guidance on how to tackle it.
You should start reading three pieces of documentation:
The Fortran 90 standard (alternatively, other versions), which tells you what is legal, standard Fortran and what is not. Whenever you find some error, look at your code and check if what you are doing is legal, standard Fortran. Likely, the code in question will either be completely nonstandard (e.g. REAL*8, although that extension is fairly well understood) or rely on unspecified behaviour that Intel Fortran and GFortran are interpreting in different ways.
The GFortran manual for your version, which tells you how GFortran decides such unspecified cases, what intrinsic functions are available, how to change some options/flags, etc. This would tell you that your problem with the line lengths would be solved by adding -ffree-line-length-none.
The Intel Fortran manual for your version, which in cases of non-standard or unspecified behaviour, will allow you to know what the code you are reading was written to do, e.g. the behaviour that you would expect. In particular, it will allow you to decipher what the compiler flags that are currently being used mean. They may or may not need translation to GFortran, e.g. /Qsave will need to become -f-no-automatic.
A concrete example of interpretative differences within the range allowed be the standard: until Fortran 2003, the units for the "record length" in random access record files were left unspecified. Intel Fortran used "one machine word" (4 bytes in x86) while GFortran used 1 byte. Both were compliant with the standard letter, but incompatible.
Furthermore, even when coding "to standard", you may hit a wall if the compiler does not implement part of the Fnn standard, or it is buggy. Case in point: Intel Fortran 12.0 (old, but it's what I work with) does not the implement the ALLOCATE(y, SOURCE=x) construct for polymorphic x (the "clone allocation"). On the other hand, GFortran has not completely implemented FINAL type-bound procedures (destructors).
In both cases, you will need to find workarounds. For example, for the first issue you can use a special form of the INQUIRE statement (kudos to #haraldkl). In other cases, the workaround might even involve using some kind of feature detection (see autoconf, CMake, etc.) and storing the results as PARAMETER variables in a config.f90 file that is included by your code. Your code would then take decisions based on it, as in:
! config.f90.in (things in #x# would get subtituted by automake, for example)
INTEGER, PARAMETER :: RECORD_LEN_BYTES = #RECORD_LEN_BYTES#
! Some other file which opens a file
INCLUDE "config.f90"
!...
OPEN(u, FILE='DE430.BIN', ACCESS='direct', FORM='unformatted', RECL=56 / RECORD_LEN_BYTES)
People have been having complaints about following the standard since at least the 60s. But those cDEC$ features were put in a for good reasons...
It is valuable to cross compile though and you usually have things caught in one compiler or the other.
For you question #1 "The GNU Fortran is not able to read lines that are too long and I get errors during compilation. As a result I have to break it into multiple lines using the '&' symbol"
In the days of old there was:
options/extended_source
SUBROUTINE...
In fort it is -132, but I have not found a gfortran equivalent to -132 . It may be -ffixed-line-length-n -ffixed-line-length-none -ffree-line-length-n -ffree-line-length-none per the link: http://www.math.uni-leipzig.de/~hellmund/Vorlesung/gfortran.html#SEC8
Also the ifort standard for .f90 and .f95 is the the compiler switch '-free' '-fixed' is the standard <.f90... However one can use -fixed with .f90 and use column 6 and 'D' in column #1... Which is handy with '-D_lines' or '-DD'.
Per the link: https://software.intel.com/sites/default/files/m/f/8/5/8/0/6366-ifort.txt
For you question #2: "A module D.f90 contains all the Global variables declared. However, now I during compilation i get error is in module B.F90. The error I get is 'Unclassified Statement Error', I was able to fix it in some subroutines and functions by locally declaring the variables again."
You probably need to put in the offending line, if you can get an IP waiver.
Making variables local if they are expected to be shared in a /common/ or shared in a module will not work.
If there were in /common/ or PUBLIC then they are shared.
If they are local then they are PRIVATE.
it would be easy to get that error if a PRIVATE statement was in the wrong place, or a USE statement was omitted.
I was told to post compiling questions on stackoverflow so this is the same question I've posted to Ubuntu Ask!:
I'm trying to compile a program that came with a Makefile. The makefile uses f77 and it seems that the programs call several f95 intrinsics. When I try to compile I get:
plotkit.a(userid.o): In function userid_':
fort77-5163-1.c:(.text+0x13e): undefined reference togetgid_' fort77-5163-1.c:(.text+0x234): undefined reference to `getuid_' collect2: error: ld returned 1 exit status
I also get the same error with fdate on another program in this distribution. I've tried to change the makefile to use different compilers such as gfortran) and they all cause MORE errors.
My question is how do I get getgid, getuid, and fdate to work with a f77 program? I'm additionally confused because there are getgid and getuid man pages but no installation on ubuntu?
I have a 64 bit 14.04 LTS installation.
Thanks for any ideas.
By default, gfortran (and other Fortran compilers) mangle procedure names by adding an underscore. When you reference getgid in source, the compiler changes that to getgid_. If the function getgid isn't defined in Fortran source, e.g. in C, then this will cause link errors such as the one you are encountering.
The functions getgid, getuid, etc are not Fortran functions, they are standard C library functions. If the code you are using is from somewhere else, look and see if the provided Makefiles have options listed to disable default underscoring by Fortran. For gfortran, this option is -fno-underscoring. Append this to the compiler flags used for the Fortran compiler in the makefile. For other Fortran compilers, consult their documentation for similar options.
If you aren't restricted to F77 and can make use of modern Fortran features, the other option is to fix this by providing interoperable interfaces for C library functions. e.g.
interface
function getgid() bind(C,name='getgid')
use iso_c_binding
implicit none
integer(c_int32_t) :: getgid
end function getgid
end interface
This will define an explicit interface for the C library function getgid so that you can call it from a modern Fortran implementation. You would define interfaces like this for each of the C library functions you need to call.
* As an aside, while the above interface works and is portable from a modern Fortran perspective, it isn't 100% portable from a C library perspective. The GNU implementation of getgid returns the type gid_t which though a long chain of typedefs is finally related to a true type in the files /usr/include/bits/types.h and /usr/include/bits/typesizes.h as an unsigned 32 bit integer. Fortran doesn't have unsigned types so while the storage sizes will match, if these functions ever return values above around 2 billion, they will be misinterpreted in Fortran as negative values. Also, since the storage type of gid_t is defined in the "bits" C header tree, they are potentially non-portable (not sure if the storage size is specified in POSIX or some other standard or implementation dependent).
I have a big, old, FORTRAN 77 code that has worked for many, many years with no problems.
Double-precision is not enough anymore, so to convert to quadruple-precision I have:
Replaced all occurrences of REAL*8 to REAL*16
Replaced all functions like DCOS() into functions like COS()
Replaced all built-in numbers like 0.d0 to 0.q0 , and 1D+01 to 1Q+01
The program compiles with no errors or warnings with the gcc-4.6 compiler on
operating system: openSUSE 11.3 x86_64 (a 64-bit operating system)
hardware: Intel Xeon E5-2650 (Sandy Bridge)
My LD_LIBRARY_PATH variable is set to the 64-bit library folder:
/gcc-4.6/lib64
The program reads an input file that has numbers in it.
Those numbers used to be of the form 1.234D+02 (for the double-precision version of the code, which works).
I have changed them so now that number is 1.234Q+02 , however I get the runtime error:
Bad real number in item 1 of list input
Indicating that the subroutine that reads in the data from the input file (called read.f) does not find the first number in the inputfile, to be compatible with what it expected.
Strangely, the quadruple-precision version of the code does not complain when the input file contains numbers like 1.234D+02 or 123.4 (which, based on the output seems to automatically be converted to the form 1.234D+02 rather than Q+02), it just does not like the Q+02 , so it seems that gcc-4.6 does not allow quadruple-precision numbers to be read in from input files in scientific notation !
Has anyone ever been able to read from an input file a quadruple-precision number in scientific notation (ie, like 1234Q+02) in FORTRAN with a gcc compiler, and if so how did you get it to work ? (or did you need a different compiler/operating system/hardware to get it to work ?)
Almost all of this is already in comments by #IanH and #Vladimi.
I suggest mixing in a little Fortran 90 into your FORTRAN 77 code.
Write all of your numbers with "E". Change your other program to write the data this way. Don't bother with "D" and don't try to use the infrequently supported "Q". (Using "Q" in constants in source code is an extension of gfortran -- see 6.1.8 in manual.)
Since you want the same source code to support two precisions, at the top of the program, have:
use ISO_FORTRAN_ENV
WP = real128
or
use ISO_FORTRAN_ENV
WP = real64
as the variation that changes whether your code is using double or quadruple precision. This is using the ISO Fortran Environment to select the types by their number of bits. (use needs to between program and implicit none; the assignment statement after implicit none.)
Then declare your real variables via:
real (WP) :: MyVar
In source code, write real constants as 1.23456789012345E+12_WP. The _type is the Fortran 90 way of specifying the type of a constant. This way you can go back and forth between double and quadruple precision by only changing the single line defining WP
WP == Working Precision.
Just use "E" in input files. Fortran will read according to the type of the variable.
Why not write a tiny test program to try it out?