I have a list of vectors that I want to gather in a single matrix Z
. Here is the code I tried to use :
import sys, slepc4py slepc4py.init(sys.argv) from petsc4py import PETSc from slepc4py import SLEPc n = 5 d = 10 l = [] # creation of the list of vectors for i in range(d): v = PETSc.Vec().create() v.setSizes(n) v.setFromOptions() v.set(i) l.append(v) Z = PETSc.Mat().create() Z.setSizes([n, d]) Z.setFromOptions() Z.setUp() for i, v in enumerate(l): # Z.setValuesBlocked(range(n), i, v) Z.setValues(range(n), i, v) Z.assemble() Z.view() # to display the matrix in the terminal
I tried setValues
and setValuesBlocked
. When I run this script on one core, that works well. The result printed is :
row 0: (0, 0.) (1, 1.) (2, 2.) (3, 3.) (4, 4.) (5, 5.) (6, 6.) (7, 7.) (8, 8.) (9, 9.) row 1: (0, 0.) (1, 1.) (2, 2.) (3, 3.) (4, 4.) (5, 5.) (6, 6.) (7, 7.) (8, 8.) (9, 9.) row 2: (0, 0.) (1, 1.) (2, 2.) (3, 3.) (4, 4.) (5, 5.) (6, 6.) (7, 7.) (8, 8.) (9, 9.) row 3: (0, 0.) (1, 1.) (2, 2.) (3, 3.) (4, 4.) (5, 5.) (6, 6.) (7, 7.) (8, 8.) (9, 9.) row 4: (0, 0.) (1, 1.) (2, 2.) (3, 3.) (4, 4.) (5, 5.) (6, 6.) (7, 7.) (8, 8.) (9, 9.)
but in parallel I have issues :
Traceback (most recent call last): File "t.py", line 26, in <module> Z.setValues(range(n), i, v) File "PETSc/Mat.pyx", line 885, in petsc4py.PETSc.Mat.setValues File "PETSc/petscmat.pxi", line 826, in petsc4py.PETSc.matsetvalues ValueError: incompatible array sizes: ni=5, nj=1, nv=3 Traceback (most recent call last): File "t.py", line 26, in <module> Z.setValues(range(n), i, v) File "PETSc/Mat.pyx", line 885, in petsc4py.PETSc.Mat.setValues File "PETSc/petscmat.pxi", line 826, in petsc4py.PETSc.matsetvalues ValueError: incompatible array sizes: ni=5, nj=1, nv=2
I think it’s because PetSc waits for the local indices in the function setValues
, but I don’t know how to access it (local_size
gives the local size of the matrix, if I put Z.local_size[0]
in setValues
, the result in parallel is
Mat Object: 2 MPI processes type: mpiaij row 0: (0, 0.) (1, 1.) (2, 2.) (3, 3.) (4, 4.) (5, 5.) (6, 6.) (7, 7.) (8, 8.) (9, 9.) row 1: (0, 0.) (1, 1.) (2, 2.) (3, 3.) (4, 4.) (5, 5.) (6, 6.) (7, 7.) (8, 8.) (9, 9.) row 2: (0, 0.) (1, 1.) (2, 2.) (3, 3.) (4, 4.) (5, 5.) (6, 6.) (7, 7.) (8, 8.) (9, 9.) row 3: row 4:
)
Which function or what argument should I use to fulfill this ?
EDIT :
I tried a more tedious way to fill the matrix Z
, using the following double loop :
for i, v in enumerate(l): for j in range(n): Z.setValue(j, i, v[j])
once again in sequential, that works fine, but if I run it over 2 cores here is the result, totally wrong !
Mat Object: 2 MPI processes type: mpiaij row 0: (0, 6.93107e-310) (1, 6.93107e-310) (2, 6.93107e-310) (3, 0.) (4, 6.93107e-310) (5, 6.93107e-310) (6, 6.93107e-310) (7, 6.93107e-310) (8, 6.93107e-310) (9, 6.93107e-310) row 1: (0, 0.) (1, 0.) (2, 0.) (3, 0.) (4, 0.) (5, 0.) (6, -1.) (7, -1.) (8, 0.) (9, 0.) row 2: (0, 1.63042e-322) (1, 1.63042e-322) (2, 1.63042e-322) (3, 1.63042e-322) (4, 1.63042e-322) (5, 1.63042e-322) (6, 1.63042e-322) (7, 1.63042e-322) (8, 1.63042e-322) (9, 1.63042e-322) row 3: (0, 0.) (1, 0.) (2, 0.) (3, 0.) (4, 0.) (5, 0.) (6, 0.) (7, 0.) (8, 0.) (9, 0.) row 4: (0, 0.) (1, -1.) (2, 0.) (3, 0.) (4, -1.) (5, 4.24399e-314) (6, 0.) (7, -1.) (8, -1.) (9, 0.)
Advertisement
Answer
Thank to the help of the team developping PetSc, I managed to do it. Here is the code :
from petsc4py import PETSc n = 10 d = 5 l = [] # creation of the list of vectors for i in range(d): v = PETSc.Vec().create(comm=PETSc.COMM_WORLD) v.setSizes(n) v.setFromOptions() v.setUp() v.set(i) l.append(v) Z = PETSc.Mat().createDense((n,d),comm=PETSc.COMM_WORLD) Z.setFromOptions() Z.setUp() for i, v in enumerate(l): r = Z.getDenseColumnVec(i) v.copy(r) Z.restoreDenseColumnVec(i) Z.assemble() Z.view()
We need to use a dense matrix, and the function getDenseColumnVec
allows to access to a column of the matrix, and modify it at will.
That works both in sequential and parallel.
Mat Object: 6 MPI processes type: mpidense 0.0000000000000000e+00 1.0000000000000000e+00 2.0000000000000000e+00 3.0000000000000000e+00 4.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 2.0000000000000000e+00 3.0000000000000000e+00 4.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 2.0000000000000000e+00 3.0000000000000000e+00 4.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 2.0000000000000000e+00 3.0000000000000000e+00 4.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 2.0000000000000000e+00 3.0000000000000000e+00 4.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 2.0000000000000000e+00 3.0000000000000000e+00 4.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 2.0000000000000000e+00 3.0000000000000000e+00 4.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 2.0000000000000000e+00 3.0000000000000000e+00 4.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 2.0000000000000000e+00 3.0000000000000000e+00 4.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 2.0000000000000000e+00 3.0000000000000000e+00 4.0000000000000000e+00