- How can I use CDABS, DCMPLX, DCONJG, DIMAG and DREAL? [Answer.]
- Are non-standard specific intrinsic functions such as CDEXP available? [Answer]
- Is there a DTIME or ETIME function? [Answer]
- Is there a FLUSH procedure? [Answer]
- Is there a GETENV procedure? [Answer]
- Is there a SYSTEM procedure? [Answer]
- Can I use ‘$’ in a format to suppress newline? [Answer]
- How can I compile a very old (Fortran 66/77) program without getting errors? [Answer]
- What does the warning “TAB format input” mean? [Answer]
- Why does the message “Byte count on numeric data type” appear? [Answer]
- Why do I get the message “KIND value does not specify a valid representation method” with the NAG compiler? [Answer]
- What does “Buffer overflow on output” mean? [Answer]
- Why do I get the message “Variable X size of N bytes is too big”? [Answer]
- How can I control the maximum size of a named constant (PARAMETER)? [Answer]
- When doing mixed-language programming, what are the functions f90_init and f90_io_finish? [Answer]
- On program termination, the warning “Floating underflow occurred”; how can I find out where this is happening? [Answer]
- On program termination, the warning “Floating underflow occurred”; how can I stop this warning from appearing? [Answer]
- How can I read unformatted files written on a system with a different file format (e.g. endianness)? [Answer]
- How can I write unformatted files so they can be read on a system with a different file format (e.g. endianness)? [Answer]
- Is it possible to redistribute applications built with the NAG Fortran Compiler? [Answer]
- How should RANDOM_SEED be used to initialise the random number generator? [Answer]
- When will Fortran NNNN feature XYZ be available?" [Answer]
- Do you have any performance tips? [Answer]
- Can I use the NAG Compiler to build OpenMPI from source (on Linux)? [Answer]
- How do I link libraries with the NAG Compiler within CMake? [Answer]
- How can I compile the versions of BLAS and LAPACK from netlib using nagfor? [Answer]
|
|||||||||||||||||||||||
Question | How can I use CDABS, DCMPLX, DCONJG, DIMAG and DREAL? | ||||||||||||||||||||||
Answer | These are not standard Fortran intrinsic functions, though they are a common extension. We recommend that they be converted to standard Fortran using the following table.
Release 6.1 of the NAG Fortran Compiler can perform these conversions for you using the integrated precision unifier tool (nagfor =unifyprecision -dcfuns your_file.f90 from the command line); the -dcfuns option is used to make the compiler recognise these functions. |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | Are non-standard specific intrinsic functions such as CDEXP available? | ||||||||||||||||||||||
Answer |
No. These functions have never been part of any Fortran standard, and there is not universal agreement on their spelling. However, they are never needed: just use the standard generic intrinsic functions: ABS, ACOS, ASIN, ATAN, ATAN2, CONJG, COS, COSH, DIM, EXP, LOG, LOG10, MAX, MIN, SIGN, SIN, SINH, SQRT, TAN and TANH can all be applied to any precision Real (and where appropriate, Complex) data. If you have a program that uses a specific intrinsic (non-standard or standard) that consists of a prefix in front of one of the functions listed above, removing the prefix (usually C, CD, CQ, D, Q or Z) is nearly always the right thing to do; for example, references to an intrinsic CEXP, DEXP, CDEXP, CQEXP, DCEXP, QEXP, ZEXP can all safely be replaced by EXP. For a few functions, the rule is slightly different: xINT and xNINT, where x is one of the prefixes listed above, should be changed to AINT or ANINT respectively. Release 6.1 of the NAG Fortran Compiler can carry out some conversions of intrinsic functions from specific to generic form for you, using the integrated precision unifier tool (nagfor =unifyprecision your_file.f90 from the command line). |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | Is there a DTIME or ETIME function? | ||||||||||||||||||||||
Answer | No.
These functions are not standard Fortran; their functionality is provided by the standard Fortran intrinsic subroutines CPU_TIME and SYSTEM_CLOCK. If you have a package that wants to use the DTIME and/or ETIME procedures, you can add one or two of the following examples to your code. The first example provides DTIME and ETIME> written entirely in standard Fortran 95 (and thus will work on any Fortran 95 compiler); the second provides DTIME and ETIME using the NAG Fortran Compiler interface to Posix. NOTE: By design, the DTIME and ETIME functions are not and cannot be thread-safe. If your code might be executed in a multi-threaded environment, you should use SYSTEM_CLOCK to measure elapsed time.
! DTIME in standard Fortran. Real Function dtime(time) Real time(2) Double Precision,Save :: last_time = 0 Double Precision this_time Intrinsic Cpu_Time Call Cpu_Time(this_time) time(1) = this_time - last_time time(2) = 0 dtime = time(1) last_time = this_time End Function ! DTIME via NAG Fortran Compiler Posix module. Real Function dtime(time) Use F90_Unix_Env,Only:tms,times Real time(2) Type(tms),Save :: lastbuf Logical :: start = .True. Type(tms) buffer Integer junk junk = times(buffer) If (start) Then lastbuf%utime = 0 lastbuf%stime = 0 start = .false. End If time(1) = buffer%utime - lastbuf%utime time(2) = buffer%stime - lastbuf%stime dtime = time(1) + time(2) lastbuf = buffer End Function ! ETIME in standard Fortran. Real Function etime(time) Real time(2) Call Cpu_Time(etime) time(1) = etime time(2) = 0 End Function ! ETIME via NAG Fortran Compiler Posix module. Real Function etime(time) Use F90_Unix_Env,Only:tms,times Real time(2) Type(tms) buffer Integer junk junk = times(buffer) time(1) = buffer%utime time(2) = buffer%stime etime = buffer%utime + buffer%stime End Function |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | Is there a FLUSH procedure? | ||||||||||||||||||||||
Answer |
Yes. Fortran 2003 standardized this facility as the FLUSH statement. Here is a simple example showing how to use it. Program slow_dots ! ! This program prints 10 dots, one per second, then finishes. ! Use Iso_Fortran_Env,Only:output_unit Implicit None Integer i Do i = 1,10 Write(*,'(a)',Advance='No') '.' Call delay Flush(output_unit) End Do Print *,'Done.' Contains Subroutine delay Integer per_second,start,now Intrinsic System_Clock Call System_Clock(Count=start,Count_Rate=per_second) If (start==-huge(start)) Stop 'No clock.' Do Call System_Clock(Count=now) If (now<start .Or. now>=start+per_second) Exit End Do End Subroutine End Program
|
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | Is there a GETENV procedure? | ||||||||||||||||||||||
Answer | Yes. Fortran 2003 standardized this facility as the GET_ENVIRONMENT_VARIABLE intrinsic procedure.
Here is a simple example showing how to use it. Program environment_example ! ! This program displays the values of the environment variables FRED and USERNAME ! (if they exist). ! Implicit None Call show('FRED') Call show('USERNAME') Contains Subroutine show(name) Character(*),Intent(In) :: name Character(:),Allocatable :: value Integer len,status Intrinsic Get_Environment_Variable Call Get_Environment_Variable(name,Status=status,Length=len) If (status==1) Then Print *,'Environment variable "',name,'" does not exist.' Else If (status/=0) Then Print *,'Unexpected error',status,'for environment variable "',name,'"' Else Allocate(Character(len) :: value) Call Get_Environment_Variable(name,Value=value) Print *,'The value of environment variable "',name,'" is "',value,'".' End If End Subroutine End Program
|
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | Is there a “SYSTEM” procedure? | ||||||||||||||||||||||
Answer |
Yes. Fortran 2008 standardized this facility as the EXECUTE_COMMAND_LINE intrinsic procedure. Here is a simple example showing how to use it. Program execute_cmd_example Call execute_command_line('echo Hello World!') End Program |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | Can I use ‘$’ in a format to suppress newline? | ||||||||||||||||||||||
Answer |
No, the NAG Fortran Compiler does not accept this extension. This extension is completely obsolete with the introduction, by Fortran 90, of non-advancing input/output. Here is an example of how to produce a prompt with standard Fortran. Program prompting Character(80) name Write (*,90000,Advance='No') 90000 Format('What is your name? ') Read *, name Print *, 'Hello ', Trim(name) End Program |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | How can I compile a very old (Fortran 66/77) program without getting errors? | ||||||||||||||||||||||
Answer |
The NAG Fortran Compiler carries out a strict check for conformance to the Fortran standard and also carries out a large number of checks for obviously incorrect code. While this is the correct behaviour for a compiler when new code is being developed, it is sometimes necessary to reduce the stringency of error checking to allow older code written to lower standards to compile. There are a number of compiler options to compile such legacy code.
|
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | What does the warning “TAB format input” mean? | ||||||||||||||||||||||
Answer | TAB format is an extension to Fortran 77, and operates when TAB characters are found in fixed form source files. Because it is an extension, a warning message is produced. This format is a bit complicated, and not recommended for new programs (use free form source instead). | ||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | Why does the message “Byte count on numeric data type” appear? | ||||||||||||||||||||||
Answer |
This is an extension to Fortran 77 that was made obsolete by Fortran 90. Instead of specifying the number of bytes, Fortran 90 has kinds of each datatype, and intrinsic functions for choosing a kind based on the desired properties (SELECTED_INT_KIND and SELECTED_REAL_KIND). The NAG Fortran Compiler also provides a module, F90_KIND, which has named constants for convenient kind selection (the names for Integer and Real/Complex are also available from the standard intrinsic module ISO_FORTRAN_ENV). The equivalence between byte sizes and kinds using these names is as follows.
The kind of an integer or real constant is specified by appending an underscore and the kind value (or name); e.g. 120_int8 is an 8-bit integer constant, and 3.14159265358979323846264338327950288_real128 is a 128-bit real value. |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | Why do I get the message “KIND value does not specify a valid representation method” with the NAG compiler? | ||||||||||||||||||||||
Answer |
The interpretation of kind values depends on the compiler. There are at least two obvious methods: sequential (1 to N, where N is the number of kinds) and byte (use the number of bytes for Integer and Real type). The NAG Fortran Compiler (and some other compilers) by default uses sequential kind numbering, so single and double precision real are REAL(1) and REAL(2), not REAL(4) and REAL(8). The disadvantage of the so-called “byte” scheme is that for the Complex type, the setting is the number of bytes for each part, i.e. half the total, which can be confusing. The compiler option ‘-kind=sequential’ (the default), ‘-kind=byte’ or '-kind=unique' selects the method. |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | What does “Buffer overflow on output” mean? | ||||||||||||||||||||||
Answer |
This means that your program attempted a sequential write, in a single record, with more bytes than will fit into the file buffer for that unit. For formatted input/output, please refer to the Compiler Manual for the current implementation limit; for unformatted input/output, the default is unlimited. To change the buffer size you can use the RECL= specifier in the OPEN statement for the file you wish to write. For example: Open(13,File="myfile",Form="Formatted",Recl=2048)will establish a buffer size of 2048 bytes on unit 13.
Note that Fortran provides the IOLENGTH= specifier in the INQUIRE statement to discover the needed value for RECL= for an unformatted file. For example: Inquire(Iolength=n) big_array Open(13,File="dump",Form="Unformatted",Recl=N)will establish a sufficiently large buffer for unit 13 to allow the entirety of big_array to be read or written in one input/output statement.
An unlimited buffer size can be established for formatted input/output by using the Fortran 2003 feature “stream access”; however, this will disable the BACKSPACE statement on that unit. For example, Open(13,File="list",Form="Formatted",Access="Stream")will open unit 13 for stream access, enabling formatting input/output of records of unlimited length, but disabling the ability to backspace the unit.
|
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | Why do I get the message “Variable X size of N bytes is too big”? | ||||||||||||||||||||||
Answer |
This means that your variable is larger than the maximum object size supported by the NAG Fortran Compiler's current mode. Please refer to the Compiler's Manual for a list of its current implementation limits. |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | How can I control the maximum size of a named constant (PARAMETER)? | ||||||||||||||||||||||
Answer |
The maximum size of a named constant is controlled with the -max_parameter_size= option. This takes a limit in megabytes (MB); the default is -max_parameter_size=50. |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | When doing mixed-language programming, what are the functions f90_init and f90_io_finish? | ||||||||||||||||||||||
Answer |
These functions are needed when the main program is in C instead of Fortran. The f90_init function initialises the Fortran environment, including the floating-point status, command-line arguments, and input/output subsystem. The f90_io_finish function writes the contents of all the Fortran output buffers to their files, and closes all the Fortran files. The following example shows how to use these functions. int main(int argc,char *argv[]) { f90_init(argc,argv); /* At this point Fortran routines can be safely called. */ f90_io_finish(); return 0; } |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | On program termination, the warning “Floating underflow occurred”; how can I find out where this is happening? | ||||||||||||||||||||||
Answer |
Floating underflow is quite common in programs, and is rarely a problem. If it is a problem, you can set the IEEE halting mode for underflow to cause the program to stop when it happens; note that you should also set the “Traceback for runtime errors (-gline)” option so that the location will be reported. The following program shows how to use IEEE halting mode to cause termination on underflow. Program underflow_halt Use Ieee_Exceptions Implicit None Call Ieee_Set_Halting_Mode(Ieee_Underflow, .True.) Call make_underflow(0.5) Contains Subroutine make_underflow(x) Real, Intent(In) :: x Real :: y Integer :: n y = x n = 1 Do y = y**2 If (y==0) Exit n = n + 1 Print *, 'Step', n, 'value', y End Do Print *, 'Zero reached at step', n End Subroutine End Program |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | On program termination, the warning “Floating underflow occurred”; how can I stop this warning from appearing? | ||||||||||||||||||||||
Answer |
The Floating underflow warning can be suppressed in two ways:
|
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | How can I read unformatted files written on a system with a different file format (e.g. endianness)? How can I write unformatted files so they can be read on a system with a different file format (e.g. endianness)? |
||||||||||||||||||||||
Answer |
Unformatted file conversion is provided by three mechanisms:
|
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | Is it possible to redistribute applications built with the NAG Fortran Compiler? | ||||||||||||||||||||||
Answer |
Yes, it is possible. The easiest way to do this is to link the NAG Fortran Compiler run time library statically using the -unsharedrts option. If you link the NAG Fortran Compiler run time library dynamically, the recipient of the executable must have their own copy of the Compiler's runtime. In general, the installation directories will differ, so the recipient must arrange for the received executable to be able to discover the new location of the Compiler's runtime. On Linux, this is usually achieved by adding the appropriate directory to the LD_LIBRARY_PATH environment variable. On macOS, this can be achieved by adding the appropriate directory to the DYLD_LIBRARY_PATH environment variable. On later versions of macOS, a more reliable method is to use install_name_tool(1) on a copy of the received executable. Use otool(1) to discover the location held within the executable. Then use install_name_tool -change $ otool -l a.out |grep -e libf.*rts name /opt/NAG_Fortran/lib/libf62rts.dylib (offset 24) $ install_name_tool -change /opt/NAG_Fortran/lib/libf62rts.dylib /shared/NP62/NAG_Fortran/lib/libf62rts.dylib a.out $ otool -l a.out |grep -e libf.*rts name /shared/NP62/NAG_Fortran/lib/libf62rts.dylib (offset 24) |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | How should RANDOM_SEED be used to initialise the random number generator? | ||||||||||||||||||||||
Answer |
|
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | When will Fortran NNNN feature XYZ be available? | ||||||||||||||||||||||
Answer |
We are implementing features from all revisions of the Fortran standard as soon as possible, concentrating on the ones most frequently requested. If you are interested in feature XYZ please send an expression of your interest to support@nag.co.uk and it will be passed on to the compiler developers. |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | Do you have any performance tips? | ||||||||||||||||||||||
Answer | Always try to use
If you use assumed-shape arrays and you know that the actual arguments are always contiguous (i.e. you do not pass array slices using section notation), use -Oassumed=always_contig. With this option, a runtime error occurs if a non-contiguous actual argument is detected (so it is also useful for discovering whether you use such array sections). If you are not 100% sure, but you think that this is true all or almost all of the time, use |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | Can I use the NAG Compiler to build OpenMPI from source (on Linux)? | ||||||||||||||||||||||
Answer | Yes, with OpenMPI 3.0.0 but some manual intervention is required for earlier versions. The following script has been used to successfully build OpenMPI 2.1.0 on Fedora 25: #!/bin/sh -eu MAKEOPTS="-j" FC=nagfor export FC # Some MPI procedures are called in the Fortran interface with # mismatching data types. Let the compiler allow these: FCFLAGS="-mismatch" export FCFLAGS # Hook in a temporary nagfor wrapper to convert unrecognized '-pthread' # option, supplied by libtool when linking libraries, into # '-Wl,-pthread' current_nagfor=$(which nagfor) tmp_wrap_dir=$(mktemp -d) echo "#!/bin/sh -eu" > "${tmp_wrap_dir}"/nagfor echo '"'"${current_nagfor}"'"' \ '$(echo $* | sed -e "s% -pthread% -Wl,-pthread%g")' >> "${tmp_wrap_dir}"/nagfor chmod u+x "${tmp_wrap_dir}"/nagfor # (Specify your own installation prefix here if desired; # see the OpenMPI README) install_prefix="${HOME}"/.local ( PATH="${tmp_wrap_dir}":$PATH export PATH ./configure --prefix="${install_prefix}" make ${MAKEOPTS} all ) # Run the tests without the temporary nagfor wrapper on the PATH: make ${MAKEOPTS} check ( PATH="${tmp_wrap_dir}":$PATH export PATH make ${MAKEOPTS} install ) rm "${tmp_wrap_dir}"/nagfor rmdir "${tmp_wrap_dir}" # Supplying arguments to ld via nagfor requires double -Wl indirection; # postprocess the installed OpenMPI Fortran wrappers to correct this, # and to apply the -pthread transformation from above: echo "Postprocessing Fortran wrappers..." tmp_wrappers_list=$(mktemp) find "${install_prefix}"/share/openmpi \ -name '*fort*wrapper*.txt' > "${tmp_wrappers_list}" while read -r wrapper do orig_file="$(dirname "${wrapper}")/$(basename "${wrapper}").orig" if test ! -f "${orig_file}" then cp "${wrapper}" "${orig_file}" fi sed -e "s%\(-Wl,\)%\1\1,%" -e "s%\-pthread%-Wl,-pthread%g" < "${orig_file}" > "${wrapper}" done < "${tmp_wrappers_list}" rm "${tmp_wrappers_list}" # Run a quick final test: echo "Running Fortran sanity check..." tmp_fortran_file=$(mktemp --suffix .f90) cat <<EOF> "${tmp_fortran_file}" Program foo Print '(A)', 'Hello MPI World!' End Program EOF tmp_exe=$(mktemp --suffix .exe) "${install_prefix}"/bin/mpif90 "${tmp_fortran_file}" -o "${tmp_exe}" if test "$(${tmp_exe})" != "Hello MPI World!" then echo "FAILed Fortran execution" exit_stat=1 else echo "Fortran executed OK:" ${tmp_exe} exit_stat=0 fi rm "${tmp_fortran_file}" "${tmp_exe}" exit ${exit_stat} |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | How do I link libraries with the NAG Compiler within CMake? | ||||||||||||||||||||||
Answer | The NAG Fortran Compiler uses the host system's C compiler (e.g. gcc) as its linker. Consequently, the nagfor switch -Wl,-option causes the -option switch to be passed to the host's C compiler. Software systems such as CMake assume when linking that the driving compiler is communicating directly with the system linker (e.g. ld), and they use the switch -Wl,-option for passing the option -option to this linker. Therefore, to communicate -option from a nagfor link line to the system's linker one must escape the switch twice: -Wl,-Wl,,-option. As a more complicated example, to use the start/end grouping option in GNU ld supply nagfor with the switch -Wl,-Wl,,--start-group,foo1,foo2,-Wl,,--end-group You can verify at any time that the ultimate linker is receiving the switch(es) you are expecting it to receive by running the respective nagfor line with the -dryrun switch added. Within CMake the -Wl, indirection can be integrated with the target_link_libraries function as follows: #Use cmake's find library function to assign library paths to variables find_library(naglib NAMES libnag_mkl.a PATHS ${nagdir}/lib) find_library(mkllp64 NAMES libmkl_intel_lp64.a PATHS ${mkllib}) find_library(mklgnu NAMES libmkl_gnu_thread.a PATHS ${mkllib}) find_library(mklcore NAMES libmkl_core.a PATHS ${mkllib}) #link libraries. Note quotations are just used for line continuation target_link_libraries(foo ${linker_flags} "-Wl,-Wl,,--start-group,\ ${mkllp64},${mklgnu},${mklcore},-Wl,,--end-group" ${naglib}) |
||||||||||||||||||||||
|
|||||||||||||||||||||||
Question | How can I compile the versions of BLAS and LAPACK from netlib using nagfor? | ||||||||||||||||||||||
Answer |
It's not difficult to compile LAPACK using the NAG compiler. Here's how to do it on a Linux machine, using LAPACK 3.9.0 as an example. First, obtain the lapack distribution from netlib Note that the distribution also contains a reference implementation of the BLAS. Unpack the lapack distribution tar file in a convenient place: mkdir lapack_build cd lapack_build tar zxvf lapack-3.9.0.tar.gz cd lapack-3.9.0 As explained in instructions in the README.md file that you find in the lapack-3.9.0 directory, copy the example make include file and edit to use the compiler of your choice, in our case nagfor. cp make.inc.example make.inc In make.inc, change these four lines: FC = gfortran FFLAGS = -O2 -frecursive FFLAGS_DRV = $(FFLAGS) FFLAGS_NOOPT = -O0 -frecursive to FC = nagfor FFLAGS = -O2 -ieee=full -dcfuns FFLAGS_DRV = $(FFLAGS) FFLAGS_NOOPT = -O0 -ieee=full -dcfuns Also in make.inc, find the line #TIMER = INT_CPU_TIME and remove the comment: TIMER = INT_CPU_TIME (There is a comment just above this line saying that it is suitable for use by the NAG compiler). These are the only changes you should need to make to the file make.inc. What do the compiler flags mean? (i) -dcfuns (ii) -ieee=full (At LAPACK 3.9.0 and some earlier versions) there is a small bug in one of the test data files, lapack-3.9.0/TESTING/dbal.in which contains an extraneous semicolon right at the end. Edit dbal.in to remove the semicolon, which causes a read error when one of the test programs tries to read the file. After you've changed these two files, building BLAS and LAPACK is simply a matter of typing "make". Use the -j switch to make to build faster if you have a multi-core machine: make -j This will create BLAS and LAPACK libraries, and run various test programs. If you have a fast machine it should only take a few minutes, and you should see results something like these: --> LAPACK TESTING SUMMARY <-- Processing LAPACK Testing output found in the TESTING directory SUMMARY nb test run numerical error other error ================ =========== ================= ================ REAL 1308195 0 (0.000%) 0 (0.000%) DOUBLE PRECISION 1309007 0 (0.000%) 0 (0.000%) COMPLEX 768366 0 (0.000%) 0 (0.000%) COMPLEX16 769178 0 (0.000%) 0 (0.000%) --> ALL PRECISIONS 4154746 0 (0.000%) 0 (0.000%) |
||||||||||||||||||||||
|