jameskermode / f90wrap

F90 to Python interface generator with derived type support
GNU Lesser General Public License v3.0
246 stars 83 forks source link

Arrays inside derived types seem to be broken #50

Closed MrYann closed 8 years ago

MrYann commented 8 years ago

Nevermind - The problem is elsewhere. My bad.

Edit : The problem seems to be there after all...

jameskermode commented 8 years ago

Ok, I like issues that go away by themselves!

MrYann commented 8 years ago

Wellll, it did not really go away. But I have some things to learn and try before reporting a real issue. As for now, I still have trouble with the argument passing (i thought all was by reference, but it’s not). However, following your examples, derived types seem to be passed by reference by default ; and thus should be updated by fortran routines. However, if I create a derived type containing an array, all goes wrong : initialization is strange (random numbers) and routines do not update the array.

I will report back when I have a better understanding of what is going on.


Yann

Le 25 mai 2016 à 22:17, James Kermode notifications@github.com a écrit :

Ok, I like issues that go away by themselves!

— You are receiving this because you modified the open/close state. Reply to this email directly or view it on GitHub https://github.com/jameskermode/f90wrap/issues/50#issuecomment-221694166

MrYann commented 8 years ago

Ok, my understanding is that, as it is, all arguments from python to fortran are read only (while the default is inout from f90wrap fortran to original fortran). Excepted for the contents of derived types. 1 - Would it not be more consistent (with everything) to have all arguments as in an out arguments (unless specified otherwise, of course) ? I will try to propose this at least as an option on the command-line. 2 - Arrays inside derived types seem to be broken (which originated the issue). The following minimal example demonstrates it :

module test_module
type test_type1
    real, dimension(3) :: y
end type test_type1
type test_type2
    real :: y
end type test_type2
contains
subroutine test_routine(x, z)
    type(test_type1) :: x
    type(test_type2) :: z
    do j = 1,2
        x%y(j) = 10 + j
    end do
    z%y = 4
end subroutine test_routine
end module test_module

The following python code shows that initialization of the contained array is strange (random numbers ?) and the values are not updated (while they are when the contained variable is not an array, as in test_type2). Even more so, only the first value of the array changes (to another seemingly random number) :

import test_python;
import numpy; 
x=test_python.test_module.Test_Type1(); 
z=test_python.test_module.Test_Type2(); 
print(x,z); 
test_python.test_module.test_routine(x,z); 
print(x,z)
jameskermode commented 8 years ago

I will take a look at this ASAP

MrYann commented 8 years ago

More precisely, the wrapper function does not receive the values affected to the array in python, and when the wrapper function ends, the locally created values are not brought back to the python variable. On a side note, the second item of the array of the python variable is always modified upon fortran function call. Here is an example :

    module module_test

        type real_array
            real, dimension(6) :: item
        end type real_array

        contains

        subroutine testf(x)
            implicit none
            type(real_array) :: x

            print*, "This is received in fortran : ", x%item
            x%item(4) = 4
            print*, "This is sent back to python : ", x%item        
        end subroutine testf

    end module module_test

Python test :

    from test1_python import module_test as tp 
    from numpy import zeros, ones, float32

    a = tp.Real_Array()
    a.item = ones(6, dtype=float32)  # ones leads to a segfault 11 upon calling tp.testf(a); but zeros does not ... ?
    print("This is sent to fortran : " + str(a.item))
    tp.testf(a)
    print("This is received by python : " + str(a.item))
jameskermode commented 8 years ago

Thanks for the update, I'll take a look. And sorry to be slow with the previous issues. Exam-marking season is over now!

jameskermode commented 8 years ago

(By the way, if you wrap your example code in fortran ... or python ... it is much easier to read- I've edited comments above)

jameskermode commented 8 years ago

Should now be fixed. I added a test case as f90wrap/examples/arrays_in_derived_types_issue50.

This was caused by a type conversion error: the mapping from Fortran to Numpy types used 'float' for single-precision arrays, but on 64-bit systems this is a synonym for float64 rather than float32. Double precision arrays in derived types were already working correctly.

Let me know if this fixes your more general problem and I will close this issue.

MrYann commented 8 years ago

I can not test my complete project now, because many colleagues are in vacation, but on simple test cases this seems to work. I guess we can close this issue for now.

I also propose you a few corrections as a pull request.

On a side note, i see there are some portions of your code that were already prepared for arrays of types. Do you remember what was wrong or incomplete with them ? Also, have you considered working with type(c_ptr) ? This is said to be recommended in [1]. I have read the whole page but this is clearly beyond my skills.


Yann

[1] http://www.fortran90.org/src/best-practices.html#v-using-type-c-ptr-pointer

Le 26 juil. 2016 à 12:34, James Kermode notifications@github.com a écrit :

Should now be fixed. I added a test case as f90wrap/examples/arrays_in_derived_types_issue50.

This was caused by a type conversion error: the mapping from Fortran to Numpy types used 'float' for single-precision arrays, but on 64-bit systems this is a synonym for float64 rather than float32. Double precision arrays in derived types were already working correctly.

Let me know if this fixes your more general problem and I will close this issue.

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/jameskermode/f90wrap/issues/50#issuecomment-235230968, or mute the thread https://github.com/notifications/unsubscribe-auth/AG3U_W1qV9fPXi2BuAnT74kUW_YLaLtBks5qZeKwgaJpZM4Im5Er.

jameskermode commented 8 years ago

Thanks for the quick response! I saw your pull request too, thank you, see the comment there on a failing test - this is one I added recently to avoid regressions with derived type function arguments that I was seeing in a code I'm trying to wrap at the moment.

One-dimensional arrays of derived types were already supported within other derived types and in modules. What was missing before your contribution was any support for arrays of derived types as function arguments.

I agree with you and the writers of that page that type(c_ptr) would be an alternative to the current approach based on the transfer() intrinsic, but I don't have the enthusiasm to convert the code :-)

I'll mark this issue as closed now.

MrYann commented 8 years ago

The page talking about type(c_ptr) is sketchy, to say the least. Would you have any reference to recommend, where I could learn how to use this method to wrap any argument whatsoever ? (for more straightforward arrays of types of course, but also to allow for pointer arguments ; the difficulty, there, being how to make python arguments point to memory that has been allocated by fortran)

Also, before (maybe one day) committing to the task, what method would you say is the more versatile / potent ? (at least among the 5 presented in the webpage) Indeeed, the author of this page recommends c_ptr over transfer, but it is not clear if c_ptr is the best (and what is best ?) method overall.


Yann

Le 28 juil. 2016 à 14:02, James Kermode notifications@github.com a écrit :

Thanks for the quick response! I saw your pull request too, thank you, see the comment there on a failing test - this is one I added recently to avoid regressions with derived type function arguments that I was seeing in a code I'm trying to wrap at the moment.

One-dimensional arrays of derived types were already supported within other derived types and in modules. What was missing before your contribution was any support for arrays of derived types as function arguments.

I agree with you and the writers of that page that type(c_ptr) would be an alternative to the current approach based on the transfer() intrinsic, but I don't have the enthusiasm to convert the code :-)

I'll mark this issue as closed now.

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/jameskermode/f90wrap/issues/50#issuecomment-235875434, or mute the thread https://github.com/notifications/unsubscribe-auth/AG3U_Xaez_iTOACb0q0lN2ftsaHRhMHwks5qaJpngaJpZM4Im5Er.