fortranpreprocessorreal-datatype

What is the use of _real_ preprocessor in Fortran?


I am trying to understand a part of code written in fortran. The code contains the following part:

REAL(KIND=8), DIMENSION(x,y), INTENT(INOUT) :: AR
      _REAL_,    DIMENSION(x,y), INTENT(INOUT) :: BR 

From this page , i came to know that _REAL_ is a preprocessor for precision control.

  1. What does _REAL_ actually do in this code?
  2. Can AR values be assigned to BR ? Is there type incompatibility problem between them?
  3. I was trying to assign the values of AR to BR using a C function extern "C" void assign_(double *AR, double *BR , int *x, int*y)But I am having a problem, and it seems like the problem is due to the incompatibility issue between AR and BR because if I change the above code to:
    REAL(KIND=8), DIMENSION(x,y), INTENT(INOUT) :: AR REAL(KIND=8), DIMENSION(x,y), INTENT(INOUT) :: BR , the problem is solved. Is there any problem if I changed the code this way?

Solution

  • The page that you referenced seems to be a bug report on building the Molecular Dynamics software package, Amber. I infer this from the link (.../gcc-bugs/...), from the second line of the page which states:

    !+ Specification and control of Amber's working precision
    

    and finally from the description which explains how to change the precision of the Amber build (installing a single or double precision version the software).

    If the written code you are looking at is a part of Amber, then the page you have referenced does explain what _REAL_ does in the code. Namely, it's a general type definition that based on the working precision either is replaced at compile time with real(kind=4) or real(kind=8). According to the description for Amber, the default build is double precision, which implies that when compiled, _REAL_ would be replaced with real(kind=8). This should answer question 1.

    Note that in fortran values of AR can always be assigned to BR, but they will require casting to the appropriate type. I.e. if BR is an integer array, the values of AR will be need to be casted into integers. Assuming that the written code you are looking at is for Amber again, and that the default double precision is not overriden, then BR is a double precision array just as AR is, so values can be freely assigned between them.

    As for question 3., you maybe need to define a macro so that _REAL_ actually does mean double precision. While not often discussed, many fortran compilers will happily apply a preprocessor. For automatic preprocessing (allowing the compiler to determine the flags), one just needs to ensure that the fortran source file has the correct extension, such as .F90, .F, .fpp, or .FPP as outlined in the first paragraph on this documentation page for gfortran (quick note that these are understood by the intel compilers as well). As I usually code in Fortran 90 or later, the extension .F90 works wonders for me. Then, probably in the header of your source file, just add the following line:

    #define _REAL_     real(kind=8)
    

    note that I add more than one space between the last underscore and real as to emphasize that there must be a space there. Doing this will allow the Fortran compiler to replace all occurrences of _REAL_ with real(kind=8) and give you a way to globally modify real precision by modifying one line without invoking a compiler flag.

    I think that doing this might get your external C reference to work.