Search code examples
moduleincludefortranpetsc

PETSC header #include'd in a module


I have a module which holds global variables. To declare some global variables, I need to use HDF5. I am also using a library, so I also need to include a header file. So the preamble of global_variable.F90 looks like this.

module global_variables

use HDF5
#include "finclude/petscsys.h"
#include "finclude/petscvec.h"

integer(HID_T) id_file
integer(HID_T) id_plist
Vec M, C, K
...

end module

Vec is a data type defined in the header file and HID_T is a data type defined in HDF5 module.

Now, I have a file which holds subroutines for I/O. This file also uses HDF5 and the same library used in global_variables.F90. So IO.F90 looks like this.

module io

use global_varibles

contains

subroutine read_input_file( vector )

Vec vector
integer HDF5err

call H5open_f( HDF5err )
...

end subroutine

end module

Question 1: compiler returns error when compiling IO.F90, saying that Vec is undefined data type. But it does not complain about HID_T. I thought global_variables module already contains both HDF5 modules and header files, using global_variables module in IO.F90 will handle every data type declaration but it seems not. Could you please help me understand what I am understanding wrong?

Question 2: Is there a way to restrict the effect of #include to the module where it is declared?

PS. If I include #include "finclude/petscvec.h" in IO.F90, which declares Vec, then it compiles well.


Solution

  • The syntax

    Vec vector
    

    is completely alien to Fortran. It works only because Vec is a C pre-processor (CPP) macro defined in the header file "finclude/petscvec.h" as

    #define Vec PetscFortranAddr
    

    That means that you must include the header file in every Fortran file in which you use the above syntax with Vec. The macro cannot be inherited using the Fortran use because it is not a part of Fortran.

    The PetscFortranAddr is in the end defined in "finclude/petscdef.h" as an integer with 4 or 8 bytes depending on your system.

    There is probably nothing you can do except reverse engineering what it in the end the pre-processor makes to be, but I wouldn't go that way, it may be unportable.