F2PY: передача одноэлементных массивов в Фортран - PullRequest
3 голосов
/ 29 января 2010

Следующий код Фортрана заполняет двумерный массив x значением v

      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

Почему это утверждение не выполняется?

Ответы [ 2 ]

3 голосов
/ 21 октября 2010

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

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

fill(x, 2.0).

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

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

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

0 голосов
/ 28 октября 2013

У меня только что была эта проблема. Ни 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, который также работает с одноэлементными массивами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...