2012-06-28 2 views
6

У меня есть массив, который считывается из подпрограммы fortran как 1D-массив через f2py. Тогда в питоне, что массив получает реорганизован:f2py - предотвратить переупорядочение массива

a=np.zeros(nx*ny*nz) 
read_fortran_array(a) 
a=a.reshape(nz,ny,nx) #in fortran, the order is a(nx,ny,nz), C/Python it is reversed 

Теперь я хотел бы передать этот массив обратно в FORtran в качестве 3D-массива.

some_data=fortran_routine(a) 

Проблема в том, что f2py продолжает пытаться транспонировать a перед передачей fortran_routine. Фортран процедура выглядит следующим образом:

subroutine fortran_routine(nx,ny,nz,a,b) 
real a 
real b 
integer nx,ny,nz 
!f2py intent(hidden) nx,ny,nz 
!f2py intent(in) a 
!f2py intent(out) b 
... 
end subroutine 

Как предотвратить все Транспонирование назад и вперед? (Я полностью счастлив использовать различные соглашения индексирования массива на двух языках).

EDIT

кажется, что np.asfortranarray или np.flags.f_contiguous должны иметь какую-то часть в решении, я просто не могу показаться, чтобы выяснить, какая часть, которая является (или может быть ravel с последующим reshape(shape,order='F')?

EDIT

кажется, этот пост вызвало некоторое замешательство. проблема здесь состоит в том, что f2py попытки сохранить индексная схема вместо расположение памяти. Итак, если у меня есть массив numpy (в порядке C) с формой (nz, ny, nx), то f2py пытается сделать массив в форме forform тоже (nz, ny, nx). Если f2py сохранял формат памяти, массив имел бы форму (nz, ny, nx) в python и (nx, ny ,nz) в fortran. Я хочу сохранить макет памяти.

+0

привет mgilson, быстрый вопрос относительно этой самой проблемы. Я написал код fortran, который принимает 3D-массив как входной: – toylas

ответ

2

Похоже, что ответ является достаточно простой:

b=np.ravel(a).reshape(tuple(reversed(a.shape)),order='F') 

работы, но, видимо, это то же самое, как:

b=a.T 

поскольку транспонирования возвращает представление и быстрый взгляд на b.flags по сравнению с a.flags показывает, что это то, что я хочу. (b.flags - F_CONTIGUOUS).

+0

Невероятно простое решение для того, что казалось очень сложной задачей. Отличный ответ. – Chiel

5

Fortran не отменяет порядок оси, он просто хранит данные в памяти иначе, чем C/Python. Вы можете указать numpy для хранения данных в порядке Fortran, который не совпадает с обращением осей.

Я хотел бы переписать код, как это

a=np.zeros(nx*ny*nz) 
read_fortran_array(a) 
a=a.reshape(nx,ny,nz, order='F') # It is now in Fortran order 

Теперь f2py не будет пытаться изменить порядок массива при прохождении.

Как примечание стороны, это также будет работать

a=a.reshape(nx,ny,nz) # Store in C order 

, потому что за кулисами, f2py выполняет эти операции при передаче массива C-заказ на Fortran рутина:

a=a.flatten() # Flatten array (Make 1-D) 
a=a.reshape(nx,ny,nz, order='F') # Place into Fortran order 

Но конечно, более эффективно хранить в порядке Fortran с самого начала.

В общем, вам не придется беспокоиться о заказе массива, если у вас нет критически важного раздела, потому что f2py позаботится об этом для вас.

+0

Еще проще было бы передать order = 'F' paramter для первоначального вызова numpy.zeros. Тогда не требуется никаких изменений или переупорядочения. – DaveP

+0

Прошу прощения за медленную обратную связь на этом (я был вне города). Я действительно не понимаю ваше решение здесь. 'a = a.reshape (nx, ny, nz)' is * не то, что я хочу *, так как 'nx' должен быть быстрым индексом (здесь это медленный индекс). Я не могу использовать первое решение, так как я написал намного больше кода, предполагая индексирование C/Python на стороне python. Я попробовал 'b = a.flatten(). Reshape (tuple (reverse (a.shape)), order = 'F')', но это не сработало (ошибка: '0-е измерение должно быть зафиксировано на 0 но получил 448'). – mgilson

+1

извините. Ошибка ID10T. PEBKAC, что угодно. 'b = a.flatten(). reshape (tuple (reverse (a.shape)), order = 'F')' работает (спасибо за идею). Эффективность здесь не должна быть проблемой, поскольку numpy не делает копию данных массива, а только изменение метаданных. «Обратный» должен быть там, поскольку я использую индексирование C/Python в части C/Python и индексирование Fortran в части fortran кода. Это имеет наибольшее значение (для меня) таким образом. (Если вы обновите сообщение, чтобы включить это, я с радостью приму его ответ). – mgilson

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