2010-01-29 2 views
3

Следующая Fortran код заполняет 2D массив х со значением VF2PY: Передача одноэлементные массивы FORtran

 subroutine fill(x,v,m,n) 
     real*8 x(m,n),v 
     integer m,n,i 
cf2py intent(in) :: x,v,m,n 
     forall(i=1:m,j=1:n) x(i,j) = v 
     end 

При вызове этой функции из Python:

x = numpy.array([[[0.0]]],order='F') 
fill(x[:,:,0],2.0) 
assert(x[0,0,0]==2.0) # Assertion failed 

Почему это утверждение не суметь ?

+0

Um ... 'copy (x, y)' Вы имеете в виду 'copy (x, y, 1)'? – dmckee

ответ

3

x должен быть объявлен как intent(inout), если вы хотите, чтобы он передавал значения обратно вызывающему абоненту.

Однако это вызывает дополнительную проблему, поскольку проходящие массивные срезы не работают для массивов intent(inout). В этом простом примере вы можете обойти его, позвонив из python:

fill(x, 2.0).

Если вы действительно хотели передать кусочек, то вам нужно объявить х, как намерение (в, из), и звонить из питона: x[:,:,0] = fill(x[:,:,0],2.0)

Описание различных атрибутов можно найти по адресу:

http://cens.ioc.ee/projects/f2py2e/usersguide/index.html#attributes

0

У меня только была эта проблема. Ни intent(inout), ни intent(inplace) не зафиксировано. Проблема, очевидно, заключается в процедуре проверки массива array_from_pyobj() в fortranobject.c, которая поставляется с f2py и связана с каждым модулем, который строит. array_from_pyobj() делает все возможное, чтобы любой вход преобразуется в непрерывный массив должным образом, выполняя множество проверок. Один из них не работает должным образом с одноэлементными массивами, так что создается копия вместо работы с исходным массивом.

Можно исправить это, но ... ну ... Я не хочу, чтобы какой-либо из этих материалов полиморфизма в интерфейсе для библиотеки производительности в любом случае ... У меня есть класс Python, который обертывает вызовы библиотеки, которые уже гарантируют что все аргументы передаются правильно.

Так что мое исправление было сделать свою собственную копию fortranobject.c и просто заменить array_from_pyobj() следующей фиктивной версии:

extern PyArrayObject * 
array_from_pyobj(const int type_num, npy_intp *dims, 
       const int rank, const int intent, PyObject *obj) { 

    int i; 
    PyArrayObject *arr = (PyArrayObject *)obj; 

    for (i=0; i<arr->nd; ++i) 
     dims[i] = arr->dimensions[i]; 
    return arr; 
} 

Мой план должен использовать оригинальный fortranobject.c во время разработки моего Python класса-оболочки, где правда, преимущество заключается в том, чтобы получать нежные сообщения об ошибках вместо жестких сбоев каждый раз, когда вы ошибаетесь, вызывая библиотечную функцию. Как только я уверен, что все вызовы библиотеки работают, я буду использовать свой пользовательский fortranobject.c, который также работает с одноэлементными массивами.

Смежные вопросы