jameskermode / f90wrap

F90 to Python interface generator with derived type support

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

no issue: this was an programming error (optional intent(out) paramater array returned with wrong values)

epitalon opened this issue · comments

Hi,

I have a Fortran routine with some input characters of type "characters" and some optional ouput array parameters. When the caller (in Python) passes one optional array, that array is filled correctly by the called subroutine. If the caller passes all optional arrays, they all return filled with the same values (which is wrong for all of them but one).

The same calling program in Fortran does not show this problem.

Here is the fortran routine :

MODULE mvars
CONTAINS
SUBROUTINE vars(N, optCON, optT, optP, &
pco2_deriv, fco2_deriv )

IMPLICIT NONE
INTEGER, PARAMETER :: r4 = KIND(1.0)

! Input variables
!> number of records
INTEGER, INTENT(in) :: N

CHARACTER(6), INTENT(in) :: optCON
CHARACTER(7), INTENT(in) :: optT
CHARACTER(2), INTENT(in) :: optP

! Optional output variables:
REAL(kind=r4), OPTIONAL, INTENT(out), DIMENSION(6,N) :: pco2_deriv
REAL(kind=r4), OPTIONAL, INTENT(out), DIMENSION(6,N) :: fco2_deriv

! Local variables
INTEGER :: j

IF (PRESENT(pco2_deriv)) THEN
DO j=1,6
pco2_deriv(J,:) = REAL(N)+REAL(J)
END DO
ENDIF
IF (PRESENT(fco2_deriv)) THEN
DO j=1,6
fCO2_deriv(J,:) = REAL(N)+REAL(J)+1
END DO
ENDIF

RETURN
END SUBROUTINE vars

END MODULE mvars

Here is a calling Fortran program that works :

PROGRAM test_vars

USE mvars
IMPLICIT NONE
INTEGER, PARAMETER :: r4 = KIND(1.0)
REAL(kind=r4), DIMENSION(6,1) :: ph_deriv, pco2_deriv, fco2_deriv

call vars(1, optCON='mol/kg', optT='Tinsitu', optP='db', &
pco2_deriv=pco2_deriv)
write (,) "pco2_deriv[1,0]", pco2_deriv(2,1)

call vars(1, optCON='mol/kg', optT='Tinsitu', optP='db', &
pco2_deriv=pco2_deriv, fco2_deriv=fco2_deriv)
write (,) "pco2_deriv[1,0]", pco2_deriv(2,1)

STOP

END PROGRAM test_vars

It outputs:
pco2_deriv[1,0] 3.00000000
pco2_deriv[1,0] 3.00000000
Twice the same value = 3, which is correct.

And here is a Python program that fails :

change this as appropriate

mocsy_dnad_dir = "/home/jean-marie/Documents/DNAD/mocsy-bug"

Preliminaries

import sys
import numpy as np
sys.path.append (mocsy_dnad_dir)
import mocsy

derivatives w/ respect to 6 input variables

pco2_deriv = np.zeros((6,)).astype('f')
fco2_deriv = np.zeros((6,)).astype('f')

pco2_deriv = pco2_deriv.reshape ((6,1), order='F')
fco2_deriv = pco2_deriv.reshape ((6,1), order='F')

Call subroutine 'vars()' with one optionnal output parameter (pco2_deriv)

mocsy.mvars.vars(n=1,optcon="mol/kg",optt='Tinsitu',optp='db',
pco2_deriv=pco2_deriv )

Result OK

print "pco2_deriv[1,0]", pco2_deriv[1,0]

Call subroutine 'vars()' with all optionnal output parameters (xxx_deriv, yyy_deriv, ...)

mocsy.mvars.vars(n=1,optcon="mol/kg",optt='Tinsitu',optp='db',
pco2_deriv=pco2_deriv, fco2_deriv=fco2_deriv)

Result for pco2_deriv is wrong

print "pco2_deriv[1,0]", pco2_deriv[1,0]

It outputs :
pco2_deriv[1,0] 3.0
pco2_deriv[1,0] 4.0

I have simplified my program as much as I could. I hope I have not made any mistake.
It looks like first optional output array is overwritten with values of the second optional array.

Best regards,
Jean-Marie

Thanks for reporting the resolution. Marking as closed.