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.)
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