[f2py] call-back arguments

Pearu Peterson pearu@cens.ioc.ee
Mon, 23 Jul 2001 18:49:36 +0200 (EET)


On Thu, 26 Jul 2001, Martin Wiechert wrote:

> On Monday, 23. July 2001 17:34, Pearu Peterson wrote:
> 
> > expressions n,m=shape(..) have no effect. If the cb_f would be defined as
> > cb_f(m,x) then the optional attribute for m would change the signature
> > so that in python one would have cb_py(x,[m]).
> >
> > Note that these restrictions are not actually restrictions: there is no
> > use for the mentioned attributes and initializations in the callback
> > functions. For instance, the values of m,n are already initialized in
> > Fortran side, and resetting them makes no sense.
> 
> Confusing stuff, this ;-)

Sorry about this. I tried to explain it in short as the long explanation
would be also rather confusing.

> One last (I hope) question:
> Can one (still in call-backs) combine intent(out) with optional?

No. intent(out) "removes" the argument from the argument list as seen from
a Python side. So, the optional attribute has no effect.

> I have a Fortran library function which depending on a switch IOPT does or 
> does not expect the call-back function FCN to return a Jacobian (or a row of 
> it) in FJAC. From the original doc:
> 
> C         SUBROUTINE FCN(IFLAG,M,N,X,FVEC,FJAC,LDFJAC)
> ...
> C         FJAC and LDFJAC may be ignored	, if IOPT=1.
> C         REAL FJAC(LDFJAC,N)		, if IOPT=2.
> C         REAL FJAC(N)			, if IOPT=3.
> ...
> 
> I'd like to pass Python functions which do or do not append this Jacobian to 
> the list of return values.

I suggest using intent(inout) for FJAC. It's good also for
performance: if you return FJAC (the intent(out) case) then
internally it is always copied to the Fortran FJAC but not in the
intent(inout) case. And you can control IOPT switch in Python
side. Something like the following:

iopt = 1 # or 2 or 3

def fcn_py(iflag,x,fvec,fjac):
  global iopt
  fvec[:] = ...
  if iopt==2:
    n,ldfjac = fjac.shape
    fjac[:,:] = ...
  elif iopt==3:
    n = len(fjac)
    fjac[:,0] = ...

iopt = 2
x1 = integrate_smthing(fcn_py,x0)          

Regards,
	Pearu