f2py complication due parameter array dimensions being defined in modules / common blocks - fortran

I have the following subroutine in Fortran 90:
subroutine foo(bar)
use spam ! dimension n is defined in the module spam
implicit none
real*8 bar(n)
....
end subroutine foo
Since the array dimension n is defined in module spam, I am getting errors during the compilation of the C wrapper functions (generated by f2py), like
error: ā€˜nā€™ undeclared (first use in this function)
Because the C wrapper function does not have any reference to spam or n.
What should be the solution to this?
I am currently preparing the bindings for ginormous Fortran program, a program which I have not authored. I now think that it is bad practice to pass information regarding parameters in common blocks/modules, just because it can lead to problems like this.
Is there any workaround, or do I have to refactor the whole code to add array dimensions as parameters?
Also, there is no chance of modifying the C source, because it is auto generated by f2py.

mod.f90
module m
integer :: n = 1
end module
main.f90
subroutine s
use m
real :: a(n)
print *,n
end subroutine
python:
f2py -c -m main mod.f90 main.f90
ipython
In [1]: import main
In [2]: main.s()
1
In [3]: main.m.n=5
In [4]: main.s()
5
I don't see any problem in using module variables.
---Edit---
I can confirm the problem with explicit size array dummy arguments, when the size depends on a module variable (not a named constant), i.e.:
subroutine s(a)
use m, only: n
real :: a(n)
end subroutine
One way of avoid the explicit bounds is using assumed shape arrays (a(:)). The assumed size arrays require an explicit interface, so they must be placed in a module which the calling code uses, or an interface block has to be supplied. Modules are generally preferred.

Related

Function declared in module using interface

I have a code as follows:
The function is declared in a module using an interface block
module my_subs
implicit none
interface
function cross(a,b)
integer, dimension(3) :: cross
integer, dimension(3), intent(in) :: a, b
end function cross
end interface
end module my_subs
program crosstest
use my_subs
implicit none
integer, dimension(3) :: m, n
integer, dimension(3) :: r
m = [1, 2, 3]
n = [4, 5, 6]
r = cross(m,n)
write(*,*) r
end program crosstest
function cross(a,b)
implicit none
integer, dimension(3) :: cross
integer, dimension(3), intent(in) :: a, b
cross(1) = a(2)*b(3) - a(3)*b(2)
cross(2) = a(3)*b(1) - a(1)*b(3)
cross(3) = a(1)*b(2) - a(2)*b(1)
end function cross
According to this website, the use of interface blocks allows main programs and external subprograms to interface appropriately. However, I tested different mismatch of array size scenarios, I got the following result:
Change dimension at line 6 to 2 and 4, the code cannot be compiled;
Change dimension at line 7 to 2, the code can be compiled and produce the correct output;
Change dimension at line 7 to 4, the code cannot be compiled;
Change dimension at line 27 to 2 and 4, the code can be compiled and produce the correct output;
Change dimension at line 28 to 2 and 4, the code can be compiled and produce the correct output;
I am confuse about the different scenarios I performed, because I suppose the use of interface can help me to detect any mismatch of array size. In this case, is it better for me to move the function cross(a,b) into the module my_subs using contains?
You can check the interface by putting some declarations in function cross that test whether the interface as declared in module my_subs matches what function cross thinks its interface should be:
interface in function cross:
module my_subs
implicit none
interface
function cross(a,b)
integer, dimension(3) :: cross
integer, dimension(3), intent(in) :: a, b
end function cross
end interface
end module my_subs
program crosstest
use my_subs
implicit none
integer, dimension(3) :: m, n
integer, dimension(3) :: r
m = [1, 2, 3]
n = [4, 5, 6]
r = cross(m,n)
write(*,*) r
end program crosstest
function cross(a,b) result(res)
use my_subs, only: check => cross
implicit none
integer, dimension(3) :: res
integer, dimension(3), intent(in) :: a, b
procedure(check), pointer :: test => cross
res(1) = a(2)*b(3) - a(3)*b(2)
res(2) = a(3)*b(1) - a(1)*b(3)
res(3) = a(1)*b(2) - a(2)*b(1)
end function cross
gfortran zaps this in all cases of mismatch you tested. I'm not sure that it should: if TKR of a dummy argument matches, shouldn't the rules of sequence association produce a correct invocation of the procedure? I haven't used submodules, but I think that they might do roughly the same thing as my example does.
When using an interface block to provide an explicit interface within a scope (in this case, in the module, which is then used by the main program) it is a requirement on the programmer that the specified interface matches the actual procedure.1
As given first, these things match happily. Changing the size of the function result or dummy arguments of one statement of the procedure but not the other creates a mismatch. Such code is a violation of the Fortran standard.
In general, a compiler isn't required to detect this violation. It may take your interface block on faith or it may do some extra work to see whether it should believe you. This latter is possible, especially if the external procedure is given in the same file as the interface block. You may see some error messages relating to this.
Further, if the interface block is given, the compiler will test the reference to the procedure against the interface, not the procedure's actual definition.
One failing, on the programmer's part, is if the actual argument isn't compatible with the dummy argument. Such a case is when the dummy argument is an explicit shape array but the actual argument is smaller than the dummy argument. [It isn't an error to have the actual argument larger.]
This problem is one of your cases:
interface
function cross(a,b)
integer, dimension(3) :: cross
integer, dimension(4), intent(in) :: a, b ! Dummy extent 4
end function cross
end interface
print*, cross([1,2,3], [4,5,6]) ! Actuals extent 3
end
Again, a compiler isn't obliged to notice this for you. It's being nice in the case where it can detect the problem.
Now, in another case you are stating that the function result is an array of shape [4] or [2]. But you are trying to assign that to an array of shape [3]. That won't work.
In conclusion, if you use an interface block to provide an explicit interface for an external procedure make sure it is correct. Turning the external procedure into a module procedure means it's the compiler's responsibility, not yours, to have the correct interface visible.
1 "Matching" here means that the characteristics of the procedure as stated by the interface block are consistent with the procedure's definition. The extents of the function result and dummy arguments are part of this. A procedure defined pure needn't have the interface block stating it is pure.

fortran type member array depending on type integer

I would like to define a type in Fortran which has an integer member and an array member depending on that integer.
program example
IMPLICIT NONE
type m
integer :: mSize = 2
double precision, dimension(mSize) :: mArray
end type m
type(m) :: test
!do stuff
end program
I do not want to use modules (yes, I know I am wasting memory!), since getting f2py and modules working together has not worked out for me (well, technically that is what I am doing, but it means in order to hide the module from f2py I have a subroutine which basically takes data and passes it without working on it and I am getting tired of the additional overhead, so I would like to work around this by including a type from an additional file)
Oh, and the bove code does not compile, gfortran complains that msize has no implicit type.

Fortran modules and C++ with Eigen

I am a Fortran user and a complete newbie to C++ and Eigen. I use modules in Fortran to be able to keep my variables, arrays and matrices in different groups and use them as needed. How to implement the idea of modules in Fortran in C++ so that I am able to pass on the data between different subroutines? I cannot paste the entire Fortran code as it is too large and there will be many new concepts which I would like to write directly in C++. Perhaps, a sample snippet or document showing how to pass on the information between C++ routines could be useful. I want to do something like this (and much more) in C++:
!*************************************************************************
! **** module file: module.f95 ****
module global
save
integer, allocatable :: kod(:,:)
end module
module local
save
integer, allocatable :: kode(:)
real*8, allocatable :: func1(:)
integer pts
end module
module fileunits
save
integer,parameter :: file1 = 11, file2 = 12
end module
!*************************************************************************
! Main program
program main
use global
use local
use fileunits
implicit none
int i,j,k,n
open(unit=file1,file='input.dat')
open(unit=file2,file='output.dat')
read(file1, *) n,pts
allocate(kod(n,pts))
allocate(kode(pts), func1(pts))
do I = 1, n
read(file1, *) (kod(i,j),j=1,pts)
do J=1,pts
kode(j) = kode(i,j)
end do
call proc1
write(file2,*) ((func1(j), j =1, pts)
end do
end program
subroutine proc1
use local
implicit none
int j
do j=1,pts
funct1(j) = kode(j) * kode(j)
...
...
end do
end subroutine

Creating a subroutine that accepts different kinds of reals

I want to implement a subroutine that can work with reals in single precision, double precision and extended precision. The only solution I can come up with is shown in the code below. This solution works but I have to duplicate the code 3 times. Can this code duplication be avoided?
module mymodule
....
! some code here
interface my_func
module procedure my_func_sp
module procedure my_func dp
module procedure my_func_ep
end interface
contains
subroutine my_func_sp(x,y)
real(kind=sp), dimension(:) :: x,y
... LONG IMPLEMENTATION HERE ...
end subroutine
subroutine my_func_dp(x,y)
real(kind=dp), dimension(:) :: x,y
... LONG IMPLEMENTATION HERE THAT IS EXACTLY THE SAME AS ABOVE ...
end subroutine
subroutine my_func_ep(x,y)
real(kind=ep), dimension(:) :: x,y
... LONG IMPLEMENTATION HERE THAT IS EXACTLY THE SAME AS THE TWO ABOVE ...
end subroutine
end module
Can this code duplication be avoided? Not really, this is the way Fortran works. You could:
Write the code once, for the highest-precision kind you care about, and have the other subroutines call that variant, casting the kinds of variables on the way in and out.
Another approach I have seen regularly is to write the computational statements in a file and to include that file in each of the subroutines. Just take care that the included statements are valid for all kinds of the type. Take care too that the same statements work across kinds. If, for example, your included lines include comparisons with a tolerance, as many numeric codes do, you may have to take special care that the tolerance is adjusted wrt the kind.
If your entire code will use single, double, or quadruple precision reals, you can define a parameter real_kind in a module and use that parameter to specify kinds throughout your code, including the declarations of real variables in your subroutine. This solution does not work if your code calls more than one of my_func_sp, my_func_dp, and my_func_ep in a single run.

Fortran: Variables changing on their own

I'm having a problem of variables getting over-written for I don't know what reason. I've posted a chunk of the code below so you can see how things are declared. The variables strain,Qi,Qf,Qd,tel and Gc are passed into the subroutine and used to calculate ssgrad,strn0,strss0.
My problem is that tel and Gc are passed into the subroutine OK but are for some reason change value during this chunk of code.
Using print statements I've found that the problem first occurs during the 2nd do loop. When I set strss0 to 0, Gc and tel change value from both being equal to 1, to seemingly random numbers: tel=11.52822 Gc=-8.789086 (Just shown for the sake of example)
Each time I run the code they are set to the same values though.
Just to let you know, this subroutine interfaces with a commercial finite element package.
Many thanks in advance for any help with this
subroutine initcalcs(strain,Qi,Qf,Qd,tel,Gc,ssgrad,strn0,strss0)
implicit none
integer :: i,j
real*8:: nstrn0,nstrs0,strn0,strnf,varsq,normvar,lmbda0,lmbdaf,
# ssgrad,t0,tt,tel,nstrnf,nstrsf,Gc
real*8, dimension(3) :: strain,stran0,stranf,strss0,strssf,var
real*8, dimension(3,3) :: Qd,Qi,Qf
lmbda0=1.0d0
nstrn0=0.0d0
do i=1,3
stran0(i)=0.0d0
stran0(i)=strain(i)*lmbda0
nstrn0=nstrn0+stran0(i)**2
end do
nstrn0=dsqrt(nstrn0)
do i=1,3
strss0(i)=0.0d0
end do
In Fortran, there are two common causes of the corruption of memory values. One is a subscript error, where you assign to an array element using an incorrect subscript value. This writes to a memory location outside of the array. The other is a disagreement between the arguments in the call to a procedure (subroutine or function) and the dummy arguments of the procedure. Either can cause problems to appear at source code locations different from the actual cause. Suggestions: inspect your code for these problems. Turn on stringent warning and error checking options of your compiler. The use of Fortran >=90 and modules gives Fortran much better ability to automatically find argument consistency problems. You could monitor the memory locations with a debugger and see what it modifying it.
I concur with M. S. B.: turn on stringent warnings and error checking and verify the subroutine calls are passing arguments that have the same type and shape (array dimensions) as the subroutine expects.
The colons in the variable declaration syntax imply this is Fortran90 or later. If that's the case, I strongly suggest using the INTENT modifier to specify whether arguments are intended to be read-only.
For example, let's assume that of the arguments passed to this routine, strain, Qi, Qf, Qd, tel, and Gc are read-only input and the arguments are ssgrad, strn0, and strss0 are returned as output; that is, whatever value they have is overwritten by this routine.
The variable declarations for the arguments would change to:
real*8, dimension(3), intent(in) :: strain
real*8, dimension(3,3), intent(in) :: Qi, Qf, Qd
real*8, intent(in) :: tel, Gc
real*8, intent(out) :: strn0, ssgrad
real*8, dimension(3), intent(out) :: strss0
The INTENT keyword is an addition to Fortran 90 which allows the user to specify which arguments are read-only (INTENT(IN)), initialized but which may be modified within the routine (INTENT(INOUT)) and which are treated as uninitialized and will be set within the routine (INTENT(OUT)).
If INTENT is not specified, it is defaults to INOUT which is consistent with FORTRAN 77 (Note that there are minor differences between INTENT(INOUT) and INTENT not being specified but they aren't relevant in this example).
A good compiler will throw an error if a routine tries to assign a value to a variable declared INTENT(IN) and will at least throw a warning if a variable declared INTENT(OUT) doesn't get assigned a value.
If possible, set INTENT(IN) on all the variables which are supposed to be read-only. This may not be possible, depending on how those variables are passed to other routines. If INTENT isn't specified on arguments to routines called within this routine, it will default to INOUT. If you pass an INTENT(IN) variable as an INTENT(INOUT) argument, the compiler will throw an error. If this is happening in code you control, you have have to specify INTENT in a number of routines. This may or may not be desirable depending on whether you want to generally improve your code or just fix this one problem really quickly.
I'm assuming some of these variables are passed to external routines in the finite element package which I 'm guessing is linked to your code rather than compiled; I'm not sure how compile-time intent checking is handled in that case.