F2py - prevent array reordering

I have an array that is read from the fortran routine as a 1D array via f2py. Then in python this array changes:

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 

Now I would like to pass this array back to fortran as a 3D array.

 some_data=fortran_routine(a) 

The problem is that f2py keeps trying to transpose a before passing fortran_routine. The fortran procedure is as follows:

 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 

How to prevent all carry back and forth? (I am completely happy to use the various bilingual array indexing conventions).

EDIT

It seems that np.asfortranarray or np.flags.f_contiguous should have some part in the solution, I just can not figure out which part (or maybe ravel and then reshape(shape,order='F') ?

EDIT

This message seems to have caused some confusion. The problem here is that f2py trying to save the indexing scheme instead of the memory layout. So, if I have a numpy array (in C order) with the form (nz, ny, nx) , then f2py tries to force the array to have the form (nz, ny, nx) in fortran too. If f2py kept the memory layout, the array would have the form (nz, ny, nx) in python and (nx, ny ,nz) in fortran. I want to save the memory layout.

+6
source share
2 answers

It seems like the answer is quite simple:

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

works, but apparently this is the same as:

 b=aT 

since transposition returns a view and a quick look at b.flags compared to a.flags shows that this is what I want. ( b.flags - F_CONTIGUOUS).

+2
source

Fortran does not reverse the axis order; it just stores data in memory differently than C / Python. You can tell numpy to save the data in Fortran order, which does not match the axis rotation.

I would rewrite your code like this

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

Now f2py will not try to reorder the array when passing.

As a side note, this will also work

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

because behind the scenes, f2py performs these operations when you pass an array of C-order to a Fortran procedure:

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

But of course, it’s more efficient to keep Fortran in order from the start.

In general, you don't need to worry about arranging the array unless you have a critical section, because f2py will take care of this for you.

+5
source

Source: https://habr.com/ru/post/919255/


All Articles