iso_fortran_env kind values not compile-time constant [duplicate] - fortran

In a Fortran 2003 module I'm defining a type called t_savepoint and, later, I want to define an interface for a subroutine called fs_initializesavepoint, which takes an object of type t_savepoint as only argument.
Here is the code for the whole module:
module m_serialization
implicit none
type :: t_savepoint
integer :: savepoint_index
real :: savepoint_value
end type t_savepoint
interface
subroutine fs_initializesavepoint(savepoint)
type(t_savepoint) :: savepoint
end subroutine fs_initializesavepoint
end interface
end module m_serialization
The reason why I want such an interface is that later on I will make this fortran module interoperate with C.
If I try to compile it (gfortran-4.7.0), I get the following error message:
type(t_savepoint) :: savepoint
1
Error: The type of 'savepoint' at (1) has not been declared within the interface
The error disappears if I move the definition of the type inside the subroutine; but if then I want to use the same type within many subroutines, should I repeat the definition in all of them?
Thank you in advance.
EDIT: a solution would be to move the definition of the type onto another module and then to use it in every subroutine. However I don't like this solution too much, because the type t_savepoint and the subroutines are part of the same conceptual topic.

Rightly or wrongly in an interface block you don't have access to the environment by host association. To fix this you need to import the datatype exlicitly:
[luser#cromer stackoverflow]$ cat type.f90
module m_serialization
implicit none
type :: t_savepoint
integer :: savepoint_index
real :: savepoint_value
end type t_savepoint
interface
subroutine fs_initializesavepoint(savepoint)
Import :: t_savepoint
type(t_savepoint) :: savepoint
end subroutine fs_initializesavepoint
end interface
end module m_serialization
[luser#cromer stackoverflow]$ gfortran -c type.f90
This is f2003.
However I suspect the way you have put this suggests you are not going about coding this up the best way. Better is simply to put the routine itself in the module. Then you don't need bother with the interface at all:
module m_serialization
implicit none
type :: t_savepoint
integer :: savepoint_index
real :: savepoint_value
end type t_savepoint
Contains
Subroutine fs_initializesavepoint(savepoint)
type(t_savepoint) :: savepoint
Write( *, * ) savepoint%savepoint_index, savepoint%savepoint_value
End Subroutine fs_initializesavepoint
end module m_serialization
[luser#cromer stackoverflow]$ gfortran -c type.f90
Given that modules are really designed to deal with connected entities this is really the way to do it in Fortran. It also has the advantage of only requiring a f95 compiler, so is universally available (though admittedly import is commonly implemented)

Related

subroutine using module but is outside module and also used in module through an interface

When I have a subroutine outside a module but is used by means of a "pointer assignment" and the subroutine is defined by means of an interface but the real subroutine is in a separate file and used module I get compiler errors.
So when I have the following Fortran code:
module test_mod_a
save
type test_type_a
integer :: scl_a = 0
contains
procedure :: my_subr => test_subr_a
end type test_type_a
interface
subroutine test_subr_a(this)
import test_type_a
implicit none
class(test_type_a) :: this
end subroutine test_subr_a
end interface
end module test_mod_a
and
subroutine test_subr_a(this)
use test_mod_a
implicit none
class(test_type_a) :: this
end subroutine test_subr_a
When I give the commands (gfortran version 9.3.0):
gfortran -c test_a.f90
gfortran -c test_a_subr.f90
I get the compiler error:
test_a_subr.f90:3:6:
3 | use test_mod_a
| 1
Error: ‘test_subr_a’ of module ‘test_mod_a’, imported at (1), is also the name of the current program unit
There are a few ways to overcome this problem:
replace !use test_mod_a by !use test_mod_a, only : test_type_a
include the subroutine in the module (and discarding in the subroutine the use statement and in the module the interface
all a bit cumbersome for a large project.
Is there another way?
As well as the use of only (not including the name of the procedure), there are the two other techniques for avoiding identifier re-use:
private test_subr_a in the module
Use renaming in the subroutine with use test_mod_a, self_iface => test_subr_a
However, from the look of the structure it seems the intention really is for test_subr_a to be like a module subroutine but isn't for one of two reasons:
there's been incremental development of an old program and the external subroutine now wants to be used in a "modern" way
the implementation of the subroutine is split out for reasons of file size, avoiding compilation cascades, secrecy of implementation
With the luxury of changing the code in a significant way one can handle these.
For the first reason, one could go ahead and move the subroutine into the module and take the pain of having to update other references where it was an external subroutine. As mentioned in the question.
For the second reason, submodules could be considered:
module test_mod_a
implicit none
type test_type_a
integer :: scl_a = 0
contains
procedure :: my_subr => test_subr_a
end type test_type_a
interface
module subroutine test_subr_a(this)
class(test_type_a) :: this
end subroutine test_subr_a
end interface
end module test_mod_a
submodule(test_mod_a) implementation_a
implicit none
contains
module subroutine test_subr_a(this)
class(test_type_a) :: this
end subroutine test_subr_a
end submodule implementation_a
Again, test_subr_a is no longer an external subroutine, so other references may need fixing.

passing allocated array from subroutine to the main program in fortran; use or module? interface?

I want to allocate an array in a subroutine, and then use this array in the main program and pass it to some other subroutine. In the past (F77?) the passing could be done in a common block, but nowadays the favored procedure seems to be to use a module. When I try this, as in the code example, the compiler tells me
Rank mismatch in argument ‘f’ at (1) (scalar and rank-1)
Apparently, the main program thinks that 'f' is a scalar: but, I read this code to mean that I've declared it as a one-dimensional array, both inside the subroutine and in the main program. What am I missing?
I've tried variations, such as declaring the variables as part of the module, but nothing I could think of made the compilation error-free (and some produced many more errors ;-( ). Any insight is most appreciated.
module subs
contains
subroutine makef(f)
end subroutine makef
end module subs
c-----------------------------------------------------------------------
program work
use subs
implicit none
real, allocatable :: f(:)
call makef(f)
write (*,*) f
stop
end
c---------------------------------------------------------------------
subroutine makef(f)
implicit none
real, allocatable, intent(out) :: f(:)
integer :: i
integer :: is
is=10
allocate(f(-is:is))
do i=-is,is
f(i)=i
end do
return
end subroutine makef
Modules in Fortran are not like header files in other languages which merely provide information about things defined elsewhere. There is the concept of "deferred definition" (submodules) but in this case the module should say everything about the subroutine, not simply attempt to point to its existence.
In the example of the question, we have: the main program; a module subs with module procedure makef; an external subroutine makef.
The main program uses the module subs, and its procedure makef, so reference in the main program to makef is to that module procedure not the external subroutine makef.
The module subroutine makef has the argument f which has no declaration statements, making it an implicitly declared scalar/external function. This is the compiler's message. Use implicit none in modules, just as it's in the main program and external subroutine here.
The entire definition of the subroutine should be placed in the module:
module subs
implicit none
contains
subroutine makef(f)
real, allocatable, intent(out) :: f(:)
integer :: i
integer :: is
is=10
allocate(f(-is:is))
do i=-is,is
f(i)=i
end do
end subroutine makef
end module subs
Alternatively, if one does want to refer to the later implementation of an external procedure an interface block can feature in the module without declaring the subroutine itself. In this case it will still be necessary to specify the complete interface:
module subs
implicit none
! An interface block to give an explicit interface to the external subroutine makef
interface
subroutine makef(f)
implicit none
real, allocatable, intent(out) :: f(:)
end subroutine makef
end interface
end module subs
In this case, don't prefer the interface block.
You only placed the copy of the first and the last line into the module. That can't work. You must move the whole subroutine into the module.

How do you specify a module variable as a part of dummy argument declaration inside an interface block?

I have a subroutine sub_x defined as
subroutine sub_x(n, a)
use, intrinsic :: iso_c_binding
use mod_a, only : m
implicit none
integer(c_long), intent(in) :: n
real(c_double), intent(in) :: a(1:m)
.
.
.
rest of the codes
.
.
That is, sub_x depends on a module variable m as an extent of its array argument. Now, in a separate file, the interface block of sub_x goes as follows
module mod_x
use, intrinsic :: iso_c_binding
interface
subroutine sub_x(n, a)
import :: c_long, c_double, m
integer(c_long), intent(in) :: n
real(c_double), intent(in) :: a(1:m)
end
end interface
end module mod_x
And any procedure calling sub_x will have a use mod_x statement. When trying to compile the file containing module mod_x, file_x.f90 with ifort -c file_x.f90 I got error saying "IMPORT-name must be the name of an entity in the host scoping unit. [m]" showing that the compiler was not able to resolve m. It may be able to resolve c_long and c_double because of the presence of use, intrinsic :: iso_c_binding in mod_x definition, but I may be wrong. Adding use mod_a, only : m in mod_x definition may solve the issue, but that means mod_x will depend on mod_a and I try to avoid dependency between modules.
One way that seems to work is to move the interface block to a plain text file, say interface_x.f90, and add an include "interface_x.f90" line in any procedure calling sub_x. But I try to avoid using this method because I have tens of external subroutines and it's better to have the interfaces of all of them in a single file. If I were to use this, just about any procedure having an include "interface_x.f90" will have to have use mod_a, only : m even though it doesn't need m. What's the solution?
It is not necessary to use an import statement to make an entity accessible in an interface block. It is one way, and in some cases the only way. This is not one of those cases.
The import statement controls accessibility of entities from the host scope of a scoping block (such as an interface block). In the (simplified) case of the question
module mod_x
use, intrinsic :: iso_c_binding
interface
subroutine sub_x()
import :: c_long
end
end interface
end module mod_x
the import statement makes the entity c_long from the module scope accessible in the interface specification of sub_x. That entity is itself available in the module scope because it is use associated from the module iso_c_binding.
Exactly the same entity is made accessible in the interface specification by
module mod_x
interface
subroutine sub_x()
use, intrinsic :: iso_c_binding, only : c_long
end
end interface
end module mod_x
This is much as in the actual subroutine specification of sub_x. m can be made accessible in the same way:
module mod_x
interface
subroutine sub_x(n, a)
use, intrinsic :: iso_c_binding, only : c_long, c_double
use mod_a, only : m
integer(c_long), intent(in) :: n
real(c_double), intent(in) :: a(1:m)
end
end interface
end module mod_x
(Or equivalently by combining an import with use mod_a in the module scope.)
Note that this is a module dependency whichever way you write it: mod_x depends on mod_a because the interface specified in mod_x has a characteristic determined by an entity in mod_a.

Signature matches another specific subroutine that shares the same assignment generic binding (but it doesn't)

I am migrating from ifort14 to ifort16, on 14 the code compiles and runs fine on 16 I get a compile time error which makes no sense to me. Long story short the compiler complains about a procedure whose definition is the last in the file and if I change the order it will complain about a different procedure, again the one that comes last. The error does not make any sense and this behaviour does not make sense either. Does this sound familiar to someone and do you have any idea where I could look for the problem?
I have the following structure
File1:
module model_generic
implicit none
type, abstract :: modelGen
logical, public :: init_flag = .false.
contains
procedure :: isInit => dispInitFlag_model
procedure, nopass :: taylorRule_func
procedure, nopass :: penalty_func
end type modelGen
contains
function dispInitFlag_model(this) result(init_flag)
class(modelGen), intent(in) :: this
logical :: init_flag
init_flag = this%init_flag
end function dispInitFlag_model
end module model_generic
File2:
module model_nk_generic
use model_generic
implicit none
type, abstract, extends(modelGen) :: model_nk
logical, public :: init_flag_nk = .false.
contains
procedure :: isInit => dispInitFlag_model_nk
procedure :: setIniGuess => setIniGuess_model_nk_default
! deferred procedures
procedure(obj_func), deferred :: lossFunction
procedure(IS_PC_curves), deferred :: IS_PC0
procedure(Taylor_IS_PC_curves), deferred :: taylor_IS_PC
procedure(IS_curve), deferred :: IS
procedure(PC_curve), deferred :: PC
procedure(R_trans), deferred :: R_lom
procedure(A_trans), deferred :: A_lom
procedure(eps_trans), deferred :: eps_lom
generic :: IS_PC => IS_PC0, taylor_IS_PC
end type model_nk
abstract interface
! omitted
end interface
contains
function dispInitFlag_model_nk(this) result(init_flag_nk)
class(model_nk), intent(in) :: this
logical :: init_flag_nk
init_flag_nk = this%init_flag_nk
end function dispInitFlag_model_nk
subroutine setIniGuess_model_nk_default(this,VFonGrid,grid)
class(model_nk), intent(in) :: this
real(KIND=DP), dimension(:), intent(out) :: VFonGrid
real(KIND=DP), dimension(:,:), intent(in), optional :: grid
VFonGrid = 0e0
!VFonGrid = 1._DP
end subroutine setIniGuess_model_nk_default
end module model_nk_generic
The error I receive during compilation (the above is compiled as a part of a bigger project) is
error #8437: The type/rank signature for the arguments of this specific
subroutine matches another specific subroutine that shares the same
ASSIGNMENT generic binding.
end subroutine setIniGuess_model_nk_default
^
The procedure (or its binding name) does not appear anywhere else in the programme except one module where it is called (I grepped for it to be sure). Thus it cannot share any generic binding. When I delete it the compiler gives me the same error with the dispInitFlag_model_nk procedure. When I add a do_nothing procedure then it will complain about that one. The compiler seems to always complain about the last procedure in the file.
A minimalistic test case like below compiles fine (using the same makefile). Another code without any OOP features compiles fine too.
program main
use model_generic
use model_nk_generic
class(model_nk), allocatable :: svars
end program main
Every time I do a clean compilation, all libraries that I use I compile from source except MKL but that should be linked correctly I have checked that.
Does any one have any idea what could be wrong with the source file or with my compiling environment?
Edit1: Forgot to mention the compiler flags. Normally I use ifort -openmp -O3 but I also tried my usual set of debugging flags ifort -openmp -g -p -traceback -check bounds -ftrapuv -fpe0 -O0 -warn -check uninit -gen-interfaces -warn interfaces -check all and I tried with and without the -openmp flag. At some point the compiler told me the flag was deprecated but using -qopenmp instead did not change things.
Edit2: Probably I should also have mentioned that I also use the preprocessor. And both files are preprocessed. But again on v14 it works fine and the error occurs in file2 after file1 (its dependency) is compiled.

How to make some generic programming in fortran 90/95 working with intrinsic types

I would like to program some procedure that will work with different types. I am planning to use the "include" method used in flibs described here and here. I give here a simple exemple.
! -------------------------------------------------------------- !
module data_type
type ivalue
integer :: v
end type
type rvalue
real(8) :: v
end type
end module data_type
! -------------------------------------------------------------- !
module imod
use data_type, only: T => ivalue
include "template.f90"
end module imod
! -------------------------------------------------------------- !
module rmod
use data_type, only: T => rvalue
include "template.f90"
end module rmod
! -------------------------------------------------------------- !
module mod
use imod, only:
& ivalue => T,
& iprintme => printme
use rmod, only:
& rvalue => T,
& rprintme => printme
private
public :: ivalue, rvalue
public :: printme
interface printme
module procedure iprintme
module procedure rprintme
end interface printme
end module mod
! -------------------------------------------------------------- !
program hello
use mod
implicit none
type(ivalue) :: iv
type(rvalue) :: rv
iv%v=42
rv%v=3.14
call printme(iv)
call printme(rv)
end program hello
with the included file:
contains
subroutine printme(a)
implicit none
type(T) :: a
print *,a
end subroutine printme
What bothers me is that it seems only to work with derived type, and not with intrinsic types. If the user of the module mod want to use the printme routine on an simple integer, it is really annoying for him to encapsulate it in a ivalue type and cannot doing:
integer :: a=42
call printme(a)
Is there any way to extend this method to intrinsic types, or another method that would do it in strict f90/f95 (I don't want to use the "transfer" method because of the data copy)
Tanks!
You can use the C preprocessor (CPP) in all major Fortran compilers. Usually there is a flag for invoking it (-cpp in gfortran) or it is invoked automatically if the file suffix contains capital F (.F90, .F). The preprocessor allows more powerful inclusion of sources with the usage of macros.
module imod
use data_type, only: ivalue
#define T type(ivalue)
#include "template.f90"
#undef T
end module imod
module intmod
#define T integer
#include "template.f90"
#undef T
end module intmod
and template.f90
contains
subroutine printme(a)
implicit none
T :: a
print *,a
end subroutine printme
This is not strict f90 / f95, but it uses a preprocessor, included in the compilers, which produces another (strict f95) source file and it automatically compiles it instead of the original source that contains the macros.
The compilation is then straightforward
gfortran -cpp main.f90
--Edit--
For non-believers, if you want to see some real code using this, check https://github.com/LadaF/fortran-list (disclaimer: my own code). You can use the parametric linked list there as:
list of len(20) character strings:
module str_list
#define TYPEPARAM character(20)
#include "list-inc-def.f90"
contains
#include "list-inc-proc.f90"
#undef TYPEPARAM
end module
list of integers
module int_list
#define TYPEPARAM integer
#include "list-inc-def.f90"
contains
#include "list-inc-proc.f90"
#undef TYPEPARAM
end module
list of some derived type
module new_type_list
use, new_type_module, only: new_type
#define TYPEPARAM type(newtype)
#include "list-inc-def.f90"
contains
#include "list-inc-proc.f90"
#undef TYPEPARAM
end module
You can use implicit typing. Make sure you wash your hands though - as this opens the possibility for the usual errors associated with implicit typing.
Consider a replacement for your module imod.
module imod
use data_type ! oops - I forgot this.
implicit type(itype) (q)
contains
include 'template.f90'
end module imod
(I've moved the contains statement into the including module - as it then allows you to have more than one templated include file.)
and then a procedure in included file that looks like:
! Assume anything starting with q is the type to be templated.
subroutine printme(q_arg)
print *, q_arg
end subroutine printme
If you wanted to template printme for an intrinsic type, then you just change the implicit statement in the parent module appropriately.
It's debatable, but there's also the view that you can use the module renaming facility to introduce new names for intrinsic types. If so, and if you have a F2008 compiler (so we aren't talking strict F95) then your current approach should still be able to work - using an intermediate module to allow renaming of the intrinsic integer type to have a name T.
But this confuses most (all?) compilers I've used in some way. Given that, plus the debatable legality, plus it requiring F2008, it's not a real solution.
Another way to achieve this is using Python to preprocess the Fortran source code. In the code that I'm working on, we use this Python script to preprocess the Fortran template. For instance, this is used to write interfaces for MPI functions, like this Fortran code snippet below:
module mod_mpi_grid
implicit none
#python ftypes=["integer(2)","integer(4)","integer(8)","real(4)","real(8)","complex(4)","complex(8)","logical"]
#python fsuffixes=["_i2","_i4","_i8","_f","_d","_c","_z","_l"]
#python fsizeof=["2","4","8","4","8","8","16","2"]
#python fmpitypes=["MPI_INTEGER2","MPI_INTEGER","MPI_INTEGER8","MPI_REAL","MPI_DOUBLE_PRECISION","MPI_COMPLEX","MPI_DOUBLE_COMPLEX","MPI_LOGICAL"]
#python ntypes=8
interface mpi_grid_send
#template begin
#template variable fsuffix
#python for i in range(ntypes): fsuffix=fsuffixes[i];
module procedure mpi_grid_send#fsuffix
#template end
end interface
contains
:
#template begin
#template variable fsuffix
#template variable ftype
#template variable fmpitype
#python for i in range(ntypes): fsuffix=fsuffixes[i]; ftype=ftypes[i]; fmpitype=fmpitypes[i];
subroutine mpi_grid_send#fsuffix(val,n,dims,dest,tag)
use mpi
implicit none
! arguments
#ftype, intent(in) :: val
integer, intent(in) :: n
integer, dimension(:), intent(in) :: dims
integer, dimension(:), intent(in) :: dest
integer, intent(in) :: tag
! local variables
integer :: comm, dest_rank, req, ierr
integer :: idims(0:ndmax)
idims = convert_dims_to_internal(dims)
comm = mpi_grid_get_comm_internal(idims)
dest_rank = mpi_grid_rank_internal(comm,idims(0),dest)
call mpi_isend(val,n,#fmpitype,dest_rank,tag,comm,req,ierr)
return
end subroutine mpi_grid_send#fsuffix
#template end
:
end module mod_mpi_grid
Then, at build time, the Makefile calls the following line to preprocess the template into a Fortran source code file for compilation:
python ftemplate.py < src/addons/mod_mpi_grid.tpl > src/addons/mod_mpi_grid.f90
All instances of #ftype in the subroutine are replaced by the intrinsic types integer(2), integer(4), ... logical. So, this approach works perfectly with intrinsic types!
The other parts of the code that need to send data over MPI would simply need to use mod_mpi_grid and the generic subroutine call mpi_grid_send( ... ).