Accepting F-contiguous arrays and passing them to C is questionable

Issue #95 closed
Jan Blechta created an issue

The following code shows that F-contiguous arrays can cause to a user big pain. It is questionable whether they should be accepted by petsc4py.

Passing F-contiguous array to Vec.__getitem__ goes seemsingly fine, the returned array has the same shape. One would intuitively expect the failing assert to pass.

from petsc4py import PETSc
import numpy as np

# Create Vec = 0, 1, 2, ...
v = PETSc.Vec().create(PETSc.COMM_SELF)
v.setSizes(8)
v.setType(PETSc.Vec.Type.SEQ)
idx = np.arange(v.size, dtype=PETSc.IntType)
val = np.arange(v.size, dtype=PETSc.ScalarType)
v.setValues(idx, val)

# All arrays in C-ordering
I = np.arange(6, dtype=PETSc.IntType).reshape(2, 3)
V = v[I]
assert np.allclose(I, V)  # Ok

# Index by F-ordered array
I = I.T
V = v[I]
assert I.shape, V.shape  # Ok
assert np.allclose(I, V)  # Fails because of mixed orderings!

# This is what petsc4py client has to do now
V = v[np.ascontiguousarray(I)]
assert np.allclose(I, V)  # Ok
assert np.allclose(np.ascontiguousarray(I), V)  # Ok

Comments (10)

  1. Lisandro Dalcin

    Well, you are indexing a PETSc vector with an index array of dim larger than one. I never expected Vec's to work as full fledged array containers. I hope you are not expecting me to provide the full set of indexing a broadcasting rules NumPy has! Maybe the right thing to do would be to error if the index array has dim > 1. Or try to propagate ordering and shape from indices to values. Patches welcome.

    About F-arrays, well we have them there, NumPy/SciPy is sometimes not careful enough to return them consistently. In PETSc we have things like MAT_ROW_ORIENTED to set values in matrices using Fortran order. How should we handle that case?

  2. Jan Blechta reporter

    Would it make sense to insist that values and indices passed in have the same ordering (resp. allocate values of the same ordering in the case of __getitem__)?

  3. Lisandro Dalcin

    Mmm, yes, I think that would make total sense, though it may prove tricky to implement the right way. For the allocation part, we could use PyArray_NewLikeArray, for the checks, well, I'm not sure how deep to go (just order? order and shapes? order and shapes, with special handling of 1D arrays?).

  4. Jan Blechta reporter

    1D does not need special handling; 1D array is both C and F:

    assert np.arange(8).flags['C']
    assert np.arange(8).flags['F']
    
  5. Lisandro Dalcin

    I was talking about adding checking for shapes. Because right now petsc4py does not check for equal shapes, just that the array sizes match. So, for examples, in vec.getValues(idx,val), if idx is a 2D array, but val is a 1D array (or the other way around), should that be an error?

  6. Jan Blechta reporter

    Technically checking size and ordering is enough. On the other hand if petsc4py insisted on matching shape, user can always pass in reshaped array (which is a view) to conform.

  7. Lisandro Dalcin

    OK, all right. Let's keep it simple and go for sizes and orderings. I'm not sure when I'll have time to work on this, though.

  8. Log in to comment