Re: [Numpy-discussion] f2py callback bug?
Hi James, To answer the second question, use: j = 1+numpy.array([2], numpy.int32) The answer to the first question is that the type of 1+numpy.array([2]) is numpy.int64 but Fortran function expects an array of type numpy.int32 and hence the wrapper makes a copy of the input array (which is also returned by the wrapper) before passing it to Fortran. Regards, Pearu James McEnerney wrote: > Pearu, > Thanks. a follow question. > Using fortran > > subroutine calc(j) > Cf2py intent(callback) pycalc > external pycalc > Cf2py integer dimension(1), intent(in,out):: j > > integer j(1) > print *, 'in fortran before pycalc ', 'j=', j(1) > call pycalc(j) > print *, 'in fortran after pycalc ', ' j=', j(1) > end > > in python > > import foo,numpy > def pycalc(j): > > print ' in pycalc ', 'j=', j > j[:] = 20*j > return > > print foo.calc.__doc__ > j = 1+numpy.array([2]) > print foo.calc(j, pycalc) > print j > > the output is > > calc - Function signature: > j = calc(j,pycalc,[pycalc_extra_args]) > Required arguments: > j : input rank-1 array('i') with bounds (1) > pycalc : call-back function > Optional arguments: > pycalc_extra_args := () input tuple > Return objects: > j : rank-1 array('i') with bounds (1) > Call-back functions: > def pycalc(j): return j > Required arguments: > j : input rank-1 array('i') with bounds (1) > Return objects: > j : rank-1 array('i') with bounds (1) > > in fortran before pycalc j= 3 > in pycalc j= [3] > in fortran after pycalc j= 60 > [60] > [3] > > Why is the return from foo.calc different from j? > How do I make them the same? > "return j" in pycalc doesn't change things. > > Thanks again! > > At 12:06 AM 11/25/2009, you wrote: > > >> Pearu Peterson wrote: >> >> > Hmm, regarding `intent(in, out) j`, this should work. I'll check what >> > is going on.. >> >> The `intent(in, out) j` works when pycalc is defined as subroutine: >> >>call pycalc(i, j) >> >> instead of >> >>pyreturn = pycalc(i, j) >> >> Pearu >> ___ >> NumPy-Discussion mailing list >> NumPy-Discussion@scipy.org >> http://*mail.scipy.org/mailman/listinfo/numpy-discussion > > Jim McEnerney > Lawrence Livermore National Laboratory > 7000 East Ave. > Livermore, Ca. 94550-9234 > > USA > > 925-422-1963 > > > > > ___ > NumPy-Discussion mailing list > NumPy-Discussion@scipy.org > http://mail.scipy.org/mailman/listinfo/numpy-discussion ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] f2py callback bug?
Pearu, Thanks. a follow question. Using fortran subroutine calc(j) Cf2py intent(callback) pycalc external pycalc Cf2py integer dimension(1), intent(in,out):: j integer j(1) print *, 'in fortran before pycalc ', 'j=', j(1) call pycalc(j) print *, 'in fortran after pycalc ', ' j=', j(1) end in python import foo,numpy def pycalc(j): print ' in pycalc ', 'j=', j j[:] = 20*j return print foo.calc.__doc__ j = 1+numpy.array([2]) print foo.calc(j, pycalc) print j the output is calc - Function signature: j = calc(j,pycalc,[pycalc_extra_args]) Required arguments: j : input rank-1 array('i') with bounds (1) pycalc : call-back function Optional arguments: pycalc_extra_args := () input tuple Return objects: j : rank-1 array('i') with bounds (1) Call-back functions: def pycalc(j): return j Required arguments: j : input rank-1 array('i') with bounds (1) Return objects: j : rank-1 array('i') with bounds (1) in fortran before pycalc j= 3 in pycalc j= [3] in fortran after pycalc j= 60 [60] [3] Why is the return from foo.calc different from j? How do I make them the same? "return j" in pycalc doesn't change things. Thanks again! At 12:06 AM 11/25/2009, you wrote: Pearu Peterson wrote: > Hmm, regarding `intent(in, out) j`, this should work. I'll check what > is going on.. The `intent(in, out) j` works when pycalc is defined as subroutine: call pycalc(i, j) instead of pyreturn = pycalc(i, j) Pearu ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://*mail.scipy.org/mailman/listinfo/numpy-discussion Jim McEnerney Lawrence Livermore National Laboratory 7000 East Ave. Livermore, Ca. 94550-9234 USA 925-422-1963 ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] f2py callback bug?
Pearu Peterson wrote: > Hmm, regarding `intent(in, out) j`, this should work. I'll check what > is going on.. The `intent(in, out) j` works when pycalc is defined as subroutine: call pycalc(i, j) instead of pyreturn = pycalc(i, j) Pearu ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] f2py callback bug?
Hi, It is not really a bug what you are seeing.. In pycalc when assigning j = 20 * j you create a new object `j` and the argument object `j`, that links back to Fortran data, gets discarded. So, you can change j inplace, for example: j[:] = 20*j The first argument `i` is int object that in Python is immutable, and hence cannot be changed inplace and the corresponding Fortran scalar object cannot be changed in the callback (in fact, `i` is a copy of the corresponding Fortran data value). To change `i` in Python callback, define it as an array (similar to `j`) and do inplace operations with it. Regarding pyreturn and assuming Fortran 77: you cannot return arrays or multiple object in Fortran functions. Fortran functions may return only scalars. So, the pyreturn trick will never work. The solution is to change arguments in place as with `j`. Hmm, regarding `intent(in, out) j`, this should work. I'll check what is going on.. HTH, Pearu James McEnerney wrote: > While using the call-back feature of f2py I stumbled across what appears > to be a bug and I'm asking the community to look into this. > > Background: I'm in the middle of converting some legacy fortran to python. > There is one routine that is particulary thorny that calls more easily > convertible service routines and my intention is to convert the latter > and use the callback feature of f2py to execute them within the fortran > followed by a systematic conversion of what remains. This seems to be > doable from what I've read on callback. I have not seen an example > of using callback where the python actually changes parameters that are > returned to the fortran; this is a requirement for me. While setting up > an example to illustrate this I came across a syntactically correct > situation(this means it compiles & executes) but gives the wrong answer. > Here's the code: > In fortran, source foo.f > subroutine calc(i, j) > Cf2py intent(callback) pycalc > external pycalc > Cf2py integer intent(in,out,copy):: i > Cf2py integer dimension(1), intent(in,out):: j > integer pyreturn > > integer i, j(1) > print *, 'in fortran before pycalc ','i=',i, ' j=', j(1) > pyreturn = pycalc(i, j) > print *, 'in fortran after pycalc ','i=', i, ' j=', j(1) > > end > > Standard build: f2py -c -m foo foo.f > > In python, execute > import foo,numpy > > def pycalc(i, j): > print ' in pycalc ', 'i=',i, 'j=', j > i=10*i > j = 20*j > return i, j > > print foo.calc.__doc__ > i=2 > j = 1+numpy.array([i]) > print foo.calc(i,j, pycalc) > > Here's the output: > calc - Function signature: > i,j = calc(i,j,pycalc,[pycalc_extra_args]) > Required arguments: > i : input int > j : input rank-1 array('i') with bounds (1) > pycalc : call-back function > Optional arguments: > pycalc_extra_args := () input tuple > Return objects: > i : int > j : rank-1 array('i') with bounds (1) > Call-back functions: > def pycalc(i,j): return pyreturn,i,j > Required arguments: > i : input int > j : input rank-1 array('i') with bounds (1) > Return objects: > pyreturn : int > i : int > j : rank-1 array('i') with bounds (1) > > > in fortran before pycalc i= 2 j= 3 > in pycalc i= 2 j= [3] > in fortran after pycalc i= 60 j= 3 > (60, array([3])) > > The bug: > on return to the fortran why is i=60 & j=3? > shouldn't it be i=10 & j=60 > > While that's what I expect, I might not be defining the > interface properly; but this compiles & executes. If this > is incorrect, what is? In the fortran, pyreturn appears > to be an address; how do I get the retuned values? > > I'm running > Redhat Linux > python version 2.5 > f2py version 2_3979 > numpy version 1.0.3.1 > Thanks > > Jim McEnerney > Lawrence Livermore National Laboratory > 7000 East Ave. > Livermore, Ca. 94550-9234 > > USA > > 925-422-1963 > > > > > ___ > NumPy-Discussion mailing list > NumPy-Discussion@scipy.org > http://mail.scipy.org/mailman/listinfo/numpy-discussion ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
[Numpy-discussion] f2py callback bug?
While using the call-back feature of f2py I stumbled across what appears to be a bug and I'm asking the community to look into this. Background: I'm in the middle of converting some legacy fortran to python. There is one routine that is particulary thorny that calls more easily convertible service routines and my intention is to convert the latter and use the callback feature of f2py to execute them within the fortran followed by a systematic conversion of what remains. This seems to be doable from what I've read on callback. I have not seen an example of using callback where the python actually changes parameters that are returned to the fortran; this is a requirement for me. While setting up an example to illustrate this I came across a syntactically correct situation(this means it compiles & executes) but gives the wrong answer. Here's the code: In fortran, source foo.f subroutine calc(i, j) Cf2py intent(callback) pycalc external pycalc Cf2py integer intent(in,out,copy):: i Cf2py integer dimension(1), intent(in,out):: j integer pyreturn integer i, j(1) print *, 'in fortran before pycalc ','i=',i, ' j=', j(1) pyreturn = pycalc(i, j) print *, 'in fortran after pycalc ','i=', i, ' j=', j(1) end Standard build: f2py -c -m foo foo.f In python, execute import foo,numpy def pycalc(i, j): print ' in pycalc ', 'i=',i, 'j=', j i=10*i j = 20*j return i, j print foo.calc.__doc__ i=2 j = 1+numpy.array([i]) print foo.calc(i,j, pycalc) Here's the output: calc - Function signature: i,j = calc(i,j,pycalc,[pycalc_extra_args]) Required arguments: i : input int j : input rank-1 array('i') with bounds (1) pycalc : call-back function Optional arguments: pycalc_extra_args := () input tuple Return objects: i : int j : rank-1 array('i') with bounds (1) Call-back functions: def pycalc(i,j): return pyreturn,i,j Required arguments: i : input int j : input rank-1 array('i') with bounds (1) Return objects: pyreturn : int i : int j : rank-1 array('i') with bounds (1) in fortran before pycalc i= 2 j= 3 in pycalc i= 2 j= [3] in fortran after pycalc i= 60 j= 3 (60, array([3])) The bug: on return to the fortran why is i=60 & j=3? shouldn't it be i=10 & j=60 While that's what I expect, I might not be defining the interface properly; but this compiles & executes. If this is incorrect, what is? In the fortran, pyreturn appears to be an address; how do I get the retuned values? I'm running Redhat Linux python version 2.5 f2py version 2_3979 numpy version 1.0.3.1 Thanks Jim McEnerney Lawrence Livermore National Laboratory 7000 East Ave. Livermore, Ca. 94550-9234 USA 925-422-1963 ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion