ngsPETSc 0.0.7a7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ngsPETSc/__init__.py ADDED
@@ -0,0 +1,46 @@
1
+ '''
2
+ ngsPETSc is a NGSolve/Netgen interface to PETSc
3
+ '''
4
+ from ngsPETSc.plex import *
5
+
6
+ __all__ = []
7
+
8
+ #Firedrake
9
+ try:
10
+ import firedrake
11
+ except ImportError:
12
+ firedrake = None
13
+
14
+ if firedrake:
15
+ from ngsPETSc.utils.firedrake.meshes import *
16
+ from ngsPETSc.utils.firedrake.hierarchies import *
17
+ __all__ = __all__ + ["FiredrakeMesh", "NetgenHierarchy"]
18
+
19
+ #FEniCSx
20
+ try:
21
+ import dolfinx
22
+ except ImportError:
23
+ dolfinx = None
24
+
25
+ if dolfinx:
26
+ from ngsPETSc.utils.fenicsx import *
27
+
28
+ #Netgen
29
+ try:
30
+ import ngsolve
31
+ except ImportError:
32
+ ngsolve = None
33
+
34
+ if ngsolve:
35
+ from ngsPETSc.mat import *
36
+ from ngsPETSc.vec import *
37
+ from ngsPETSc.nullspace import *
38
+ from ngsPETSc.pc import *
39
+ from ngsPETSc.ksp import *
40
+ from ngsPETSc.snes import *
41
+ from ngsPETSc.eps import *
42
+ __all__ = __all__ + ["Matrix","VectorMapping","MeshMapping",
43
+ "KrylovSolver","EigenSolver","NullSpace",
44
+ "PETScPreconditioner", "NonLinearSolver"]
45
+
46
+ VERSION = "0.0.5"
ngsPETSc/eps.py ADDED
@@ -0,0 +1,184 @@
1
+ '''
2
+ This module contains all the functions related to the SLEPc eigenvalue
3
+ solver (EPS/PEP) interface for NGSolve
4
+ '''
5
+ from petsc4py import PETSc
6
+ try:
7
+ from slepc4py import SLEPc
8
+ except ImportError:
9
+ import warnings
10
+ warnings.warn("Import Warning: it was not possible to import SLEPc")
11
+ SLEPc = None
12
+
13
+ from mpi4py import MPI
14
+
15
+ from ngsolve import GridFunction
16
+
17
+ from ngsPETSc import Matrix, VectorMapping
18
+ class EigenSolver():
19
+ """
20
+ This calss creates a SLEPc Eigen Problem Solver (EPS/PEP) from NGSolve
21
+ variational problem pencil, i.e.
22
+ a0(u,v)+lam*a1(u,v)+(lam^2)*a2(u,v)+ ... = 0
23
+ Inspired by Firedrake Eigensolver class.
24
+
25
+ :arg pencil: tuple containing the bilinear forms a: V x V -> K composing
26
+ the pencil, e.g. (m,a) with a = BilinearForm(grad(u),grad(v)*dx) and
27
+ m = BilinearForm(-1*u*v*dx)
28
+
29
+ :arg fes: finite element space V
30
+
31
+ :arg nev: number of requested eigenvalue
32
+
33
+ :arg ncv: dimension of the internal subspace used by SLEPc,
34
+ by Default by SLEPc.DECIDE
35
+
36
+ :arg solverParameters: parameters to be passed to the KSP solver
37
+
38
+ :arg optionsPrefix: special solver options prefix for this specific Krylov solver
39
+
40
+ """
41
+ if SLEPc is not None:
42
+ def __init__(self, pencil, fes, nev, ncv=SLEPc.DECIDE, optionsPrefix=None,
43
+ solverParameters=None):
44
+ self.comm = MPI.COMM_WORLD
45
+ if not isinstance(pencil, tuple): pencil=tuple([pencil])
46
+ self.penLength = len(pencil)
47
+ self.fes = fes
48
+ self.nev = nev
49
+ self.ncv = ncv
50
+ self.solverParameters = solverParameters
51
+ self.optionsPrefix = optionsPrefix
52
+ options_object = PETSc.Options()
53
+ if solverParameters is not None:
54
+ for optName, optValue in self.solverParameters.items():
55
+ options_object[optName] = optValue
56
+
57
+ self.pencilMats = []
58
+ self.pencilFlags = []
59
+ for a in pencil:
60
+ self.pencilFlags += [a.flags.ToDict()]
61
+ self.pencilMats += [Matrix(a.Assemble().mat, fes).mat]
62
+ self.pencilMats[-1].setOptionsPrefix(self.optionsPrefix)
63
+ self.pencilMats[-1].setFromOptions()
64
+ self.eps = None
65
+ self.pep = None
66
+ if self.penLength > 2:
67
+ self.isEPS = False
68
+ else:
69
+ self.isEPS = True
70
+ self.setUpEPS()
71
+
72
+ def setUpEPS(self):
73
+ '''
74
+ This function setup a SLEPc EPS if the pencil has shape either (m,a)
75
+ or is simply a single matrix.
76
+ '''
77
+ self.eps = SLEPc.EPS().create()
78
+ self.eps.setType(SLEPc.EPS.Type.KRYLOVSCHUR)
79
+ if self.penLength == 1:
80
+ flag0 = self.pencilFlags[0]
81
+ if "symmetric" in flag0.keys():
82
+ if flag0["symmetric"]:
83
+ self.eps.setProblemType(SLEPc.EPS.ProblemType.HEP)
84
+ else:
85
+ self.eps.setProblemType(SLEPc.EPS.ProblemType.NHEP)
86
+ else:
87
+ self.eps.setProblemType(SLEPc.EPS.ProblemType.NHEP)
88
+ self.eps.setOperators(self.pencilMats[0])
89
+ else:
90
+ flag0 = self.pencilFlags[0]
91
+ flag1 = self.pencilFlags[1]
92
+ if "symmetric" in flag0.keys() and "symmetric" in flag1.keys():
93
+ if flag0["symmetric"] and flag1["symmetric"]:
94
+ self.eps.setProblemType(SLEPc.EPS.ProblemType.GHEP)
95
+ else:
96
+ self.eps.setProblemType(SLEPc.EPS.ProblemType.GNHEP)
97
+ else:
98
+ self.eps.setProblemType(SLEPc.EPS.ProblemType.GNHEP)
99
+ self.pencilMats[0].scale(-1)
100
+ self.eps.setOperators(self.pencilMats[1], self.pencilMats[0])
101
+ self.eps.setDimensions(self.nev, self.ncv)
102
+ self.eps.setOptionsPrefix(self.optionsPrefix)
103
+ self.eps.setFromOptions()
104
+
105
+ def solve(self):
106
+ '''
107
+ This function solve the eigenprobelm
108
+ '''
109
+ self.eps.solve()
110
+ self.nconv = self.eps.getConverged()
111
+ if self.nconv == 0:
112
+ raise RuntimeError("Did not converge any eigenvalues.")
113
+ return self.nconv
114
+
115
+ def view(self):
116
+ '''
117
+ This function setup display the information about SLEPc EPS/PEP
118
+ '''
119
+ self.eps.view()
120
+
121
+ def eigenValue(self, i):
122
+ '''
123
+ This function return the eigenvalue of the eigenproblem
124
+
125
+ :arg i: index of the eigenvalue we are intrested in.
126
+
127
+ '''
128
+ lam = None
129
+ if self.isEPS:
130
+ lam = self.eps.getEigenvalue(i)
131
+ return lam
132
+
133
+ def eigenFunction(self, i):
134
+ '''
135
+ This function return the eigenfunction of the eigenproblem
136
+
137
+ :arg i: index of the eigenfunction we are intrested in.
138
+
139
+ '''
140
+ self.vecMap = VectorMapping(self.fes)
141
+ eigenModeReal = GridFunction(self.fes)
142
+ eigenModeImag = GridFunction(self.fes)
143
+ eignModePETScReal = self.pencilMats[0].createVecLeft()
144
+ eignModePETScImag = self.pencilMats[0].createVecLeft()
145
+ if self.isEPS:
146
+ self.eps.getEigenvector(i, eignModePETScReal, eignModePETScImag)
147
+ self.vecMap.ngsVec(eignModePETScReal,eigenModeReal.vec)
148
+ self.vecMap.ngsVec(eignModePETScImag,eigenModeImag.vec)
149
+ return eigenModeReal, eigenModeImag
150
+
151
+ def eigenValues(self, indeces):
152
+ '''
153
+ This function return the eigenvalues of the eigenproblem
154
+
155
+ :arg indeces: indeces of the eigenvalues we are intrested in.
156
+
157
+ '''
158
+ lams = []
159
+ if self.isEPS:
160
+ for i in indeces:
161
+ lams = lams + [self.eps.getEigenvalue(i)]
162
+ return lams
163
+
164
+ def eigenFunctions(self, indeces):
165
+ '''
166
+ This function return a multidim with
167
+ the eigenfunctions of the eigenproblem
168
+
169
+ :arg indeces: indeces of the eigenfunctions we are intrested in.
170
+
171
+ '''
172
+ self.vecMap = VectorMapping(self.fes)
173
+ eigenModesReal = GridFunction(self.fes, multidim=self.nev)
174
+ eigenModesImag = GridFunction(self.fes, multidim=self.nev)
175
+ k = 0
176
+ eignModePETScReal = self.pencilMats[0].createVecLeft()
177
+ eignModePETScImag = self.pencilMats[0].createVecLeft()
178
+ for i in indeces:
179
+ if self.isEPS:
180
+ self.eps.getEigenvector(i, eignModePETScReal, eignModePETScImag)
181
+ self.vecMap.ngsVec(eignModePETScReal,eigenModesReal.vecs[k])
182
+ self.vecMap.ngsVec(eignModePETScImag,eigenModesImag.vecs[k])
183
+ k += 1
184
+ return eigenModesReal, eigenModesImag
ngsPETSc/ksp.py ADDED
@@ -0,0 +1,292 @@
1
+ '''
2
+ This module contains all the functions related to the PETSc linear
3
+ system solver (KSP) interface for NGSolve
4
+ '''
5
+ from petsc4py import PETSc
6
+ from ngsolve import la, BilinearForm, FESpace, BitArray, Projector
7
+ from ngsPETSc import Matrix, VectorMapping, PETScPreconditioner, NullSpace
8
+
9
+ def createFromBilinearForm(a, freeDofs, solverParameters):
10
+ """
11
+ This function creates a PETSc matrix from an NGSolve bilinear form
12
+ """
13
+ a.Assemble()
14
+ #Setting deafult matrix type
15
+ if "ngs_mat_type" not in solverParameters:
16
+ solverParameters["ngs_mat_type"] = "aij"
17
+ #Assembling matrix if not of type Python
18
+ if solverParameters["ngs_mat_type"] not in ["python"]:
19
+ if hasattr(a.mat, "row_pardofs"):
20
+ dofs = a.mat.row_pardofs
21
+ else:
22
+ dofs = None
23
+ mat = Matrix(a.mat, (dofs, freeDofs, None), solverParameters["ngs_mat_type"])
24
+ return (a.mat, mat.mat)
25
+ raise ValueError("ngs_mat_type {} is not supported.".format(solverParameters["ngs_mat_type"]))
26
+
27
+ def createFromMatrix(a, freeDofs, solverParameters):
28
+ """
29
+ This function creates a PETSc matrix from an NGSolve bilinear form
30
+ """
31
+ #Setting deafult matrix type
32
+ if "ngs_mat_type" not in solverParameters:
33
+ solverParameters["ngs_mat_type"] = "aij"
34
+ #Assembling matrix if not of type Python
35
+ if solverParameters["ngs_mat_type"] not in ["python"]:
36
+ if hasattr(a, "row_pardofs"):
37
+ dofs = a.row_pardofs
38
+ else:
39
+ dofs = None
40
+ mat = Matrix(a, (dofs, freeDofs, None), solverParameters["ngs_mat_type"])
41
+ pscMat = mat.mat
42
+ return (a, pscMat)
43
+ if solverParameters["ngs_mat_type"] == "python":
44
+ _, pscMat = createFromAction(a, freeDofs, solverParameters)
45
+ return (a, pscMat)
46
+ raise ValueError("ngs_mat_type {} is not supported.".format(solverParameters["ngs_mat_type"]))
47
+
48
+ def createFromPC(a, freeDofs, solverParameters):
49
+ """
50
+ This function creates a PETSc matrix from an ngsPETSc PETSc Preconditioner
51
+ """
52
+ class Wrap(object):
53
+ """
54
+ This class wraps a PETSc Preconditioner as PETSc Python matrix
55
+ """
56
+ def __init__(self, a, dofs, freeDofs):
57
+ self.a = a
58
+ self.mapping = VectorMapping((dofs,freeDofs,{"bsize": [1]}))
59
+ self.ngX = a.CreateColVector()
60
+ self.ngY = a.CreateColVector()
61
+ if hasattr(a, "actingDofs"):
62
+ self.prj = Projector(mask=a.actingDofs, range=True)
63
+ else:
64
+ self.prj = Projector(mask=freeDofs, range=True)
65
+
66
+ def mult(self, mat, X, Y): #pylint: disable=W0613
67
+ """
68
+ PETSc matrix-vector product
69
+ """
70
+ self.mapping.ngsVec(X, (self.prj*self.ngX).Evaluate())
71
+ self.a.Mult(self.ngX, self.ngY)
72
+ self.mapping.petscVec((self.prj*self.ngY).Evaluate(), Y)
73
+ #Grabbing comm information
74
+ if hasattr(a, "row_pardofs"):
75
+ dofs = a.row_pardofs
76
+ comm = dofs.comm.mpi4py
77
+ elif "dofs" in solverParameters:
78
+ dofs = solverParameters["dofs"]
79
+ comm = dofs.comm.mpi4py
80
+ else:
81
+ dofs = None
82
+ comm = PETSc.COMM_SELF
83
+ pythonA = Wrap(a, dofs, freeDofs)
84
+ pscA = PETSc.Mat().create(comm=comm)
85
+ pscA.setSizes([sum(freeDofs), sum(freeDofs)])
86
+ pscA.setType("python")
87
+ pscA.setPythonContext(pythonA)
88
+ pscA.setUp()
89
+ return (a.ngsMat, pscA)
90
+
91
+ def createFromAction(a, freeDofs, solverParameters):
92
+ """
93
+ This function creates a matrix free PETSc matrix from an NGSolve matrix
94
+ """
95
+ class Wrap(object):
96
+ """
97
+ This class wraps an NGSolve matrix as PETSc Python matrix
98
+ """
99
+ def __init__(self, a, dofs, freeDofs, comm):
100
+ self.a = a
101
+ self.dofs = dofs
102
+ self.freeDofs = freeDofs
103
+ self.comm = comm
104
+ self.mapping = VectorMapping((dofs,freeDofs,{"bsize": (1,1)}))
105
+ self.ngX = a.CreateColVector()
106
+ self.ngY = a.CreateColVector()
107
+
108
+ def mult(self, mat, X, Y): #pylint: disable=W0613
109
+ """
110
+ PETSc matrix-vector product
111
+ """
112
+ self.mapping.ngsVec(X, self.ngX)
113
+ self.a.Mult(self.ngX, self.ngY)
114
+ self.mapping.petscVec(self.ngY, Y)
115
+
116
+ if hasattr(a, "row_pardofs"):
117
+ dofs = a.row_pardofs
118
+ comm = dofs.comm.mpi4py
119
+ entrysize = a.local_mat.entrysizes[0]
120
+ _, rnumberGlobal = dofs.EnumerateGlobally(freeDofs) #samrc
121
+ elif "dofs" in solverParameters:
122
+ dofs = solverParameters["dofs"]
123
+ comm = dofs.comm.mpi4py
124
+ entrysize = dofs.entrysize
125
+ _, rnumberGlobal = dofs.EnumerateGlobally(freeDofs) #samrc
126
+ else:
127
+ dofs = None
128
+ comm = PETSc.COMM_SELF
129
+ entrysize = 1
130
+ rnumberGlobal = sum(freeDofs)
131
+ pythonA = Wrap(a, dofs, freeDofs, comm)
132
+ pscA = PETSc.Mat().create(comm=comm)
133
+ pscA.setSizes(size=(rnumberGlobal*entrysize,
134
+ rnumberGlobal*entrysize), bsize=entrysize)
135
+ pscA.setType("python")
136
+ pscA.setPythonContext(pythonA)
137
+ pscA.setUp()
138
+ return (a, pscA)
139
+
140
+ parse = {BilinearForm: createFromBilinearForm,
141
+ la.SparseMatrixd: createFromMatrix,
142
+ la.ParallelMatrix: createFromMatrix,
143
+ PETScPreconditioner: createFromPC,
144
+ la.BaseMatrix: createFromAction}
145
+
146
+ class KrylovSolver():
147
+ """
148
+ This class creates a PETSc Krylov Solver (KSP) for NGSolve.
149
+ Inspired by Firedrake linear solver class.
150
+
151
+ :arg a: either the bilinear form, ngs Matrix or a petsc4py matrix
152
+
153
+ :arg dofsDescr: either finite element space
154
+
155
+ :arg p: either the bilinear form, ngs Matrix or petsc4py matrix actin as a preconditioner
156
+
157
+ :arg nullspace: either a PETSc NullSpace or ngsPETSc PETSc Preconditioner
158
+ or touple of ngsPETSc PETSc Preconditioner.
159
+
160
+ :arg solverParameters: parameters to be passed to the KS P solver
161
+
162
+ :arg optionsPrefix: special solver options prefix for this specific Krylov solver
163
+
164
+ """
165
+ def __init__(self, a, dofsDescr, p=None, nullspace=None, optionsPrefix="",
166
+ solverParameters={}):
167
+ # Grabbing dofs information
168
+ if isinstance(dofsDescr, FESpace):
169
+ freeDofs = dofsDescr.FreeDofs()
170
+ elif isinstance(dofsDescr, BitArray):
171
+ freeDofs = dofsDescr
172
+ else:
173
+ raise ValueError("dofsDescr must be either FESpace or BitArray")
174
+ #Construct operator
175
+ pscA = None
176
+ for key in parse: #pylint: disable=C0206
177
+ if isinstance(a, key):
178
+ ngsA, pscA = parse[key](a, freeDofs, solverParameters)
179
+ if pscA is None:
180
+ raise ValueError("a of type {} not supported.".format(type(a)))
181
+ if p is not None:
182
+ for key in parse: #pylint: disable=C0206
183
+ if isinstance(p, key):
184
+ if hasattr(ngsA, "row_pardofs"):
185
+ solverParameters["dofs"] = ngsA.row_pardofs
186
+ _, pscP = parse[key](p, freeDofs, solverParameters)
187
+ break
188
+ else:
189
+ pscP = pscA
190
+ #Construct vector mapping
191
+ if hasattr(ngsA, "row_pardofs"):
192
+ dofs = ngsA.row_pardofs
193
+ else:
194
+ dofs = None
195
+ if hasattr(ngsA.local_mat, "entrysizes"):
196
+ entrysize = ngsA.local_mat.entrysizes
197
+ else:
198
+ entrysize = [1]
199
+ self.mapping = VectorMapping((dofs,freeDofs,{"bsize":entrysize}))
200
+ #Fixing PETSc options
201
+ options_object = PETSc.Options()
202
+ for optName, optValue in solverParameters.items():
203
+ options_object[optName] = optValue
204
+
205
+ #Setting PETSc Options
206
+ pscA.setOptionsPrefix(optionsPrefix)
207
+ pscA.setFromOptions()
208
+
209
+ #Setting up nullspace
210
+ if nullspace is not None:
211
+ if isinstance(nullspace, (list, tuple)):
212
+ for ns in nullspace:
213
+ if isinstance(ns, PETSc.NullSpace):
214
+ pscA.setNullSpace(ns)
215
+ elif isinstance(ns, NullSpace):
216
+ if ns.near:
217
+ pscA.setNearNullSpace(ns.nullspace)
218
+ else:
219
+ pscA.setNullSpace(ns.nullspace)
220
+ else:
221
+ raise ValueError("nullspace must be either \
222
+ PETSc.NullSpace or NullSpace")
223
+ if isinstance(nullspace, PETSc.NullSpace):
224
+ pscA.setNullSpace(nullspace)
225
+ elif isinstance(nullspace, NullSpace):
226
+ if nullspace.near:
227
+ pscA.setNearNullSpace(nullspace.nullspace)
228
+ else:
229
+ pscA.setNullSpace(nullspace.nullspace)
230
+ else:
231
+ raise ValueError("nullspace must be either \
232
+ PETSc.NullSpace or NullSpace")
233
+
234
+ #Setting up KSP
235
+ self.ksp = PETSc.KSP().create(comm=pscA.getComm())
236
+ self.ksp.setOperators(A=pscA, P=pscP)
237
+ self.ksp.setOptionsPrefix(optionsPrefix)
238
+ self.ksp.setFromOptions()
239
+ self.pscX, self.pscB = pscA.createVecs()
240
+
241
+ #Attaching operator
242
+ self.ngsA = ngsA
243
+
244
+ def solve(self, b, x, mapping=None):
245
+ """
246
+ This function solves the linear system
247
+
248
+ :arg b: right hand side of the linear system
249
+ :arg x: solution of the linear system
250
+ """
251
+ if mapping is None:
252
+ mapping = self.mapping
253
+ mapping.petscVec(x, self.pscX)
254
+ mapping.petscVec(b, self.pscB)
255
+ self.ksp.solve(self.pscB, self.pscX)
256
+ mapping.ngsVec(self.pscX, x)
257
+
258
+ def operator(self):
259
+ """
260
+ This function returns the operator of the KSP solver
261
+ """
262
+ return KSPOpeator(self)
263
+
264
+ class KSPOpeator(la.BaseMatrix):
265
+ """
266
+ This class wraps a PETSc KSP solver as an NGSolve matrix
267
+ """
268
+ def __init__(self, ksp):
269
+ la.BaseMatrix.__init__(self)
270
+ self.ksp = ksp
271
+
272
+ def Shape(self):
273
+ '''
274
+ Shape of the BaseMatrix
275
+
276
+ '''
277
+ return self.ksp.ngsA.shape
278
+
279
+ def CreateVector(self,col):
280
+ '''
281
+ Create vector corresponding to the matrix
282
+
283
+ :arg col: True if one want a column vector
284
+
285
+ '''
286
+ return self.ksp.ngsA.CreateVector(not col)
287
+
288
+ def Mult(self, x, y):
289
+ """
290
+ Matrix-vector product
291
+ """
292
+ self.ksp.solve(x, y)
ngsPETSc/mat.py ADDED
@@ -0,0 +1,146 @@
1
+ '''
2
+ This module contains all the functions related to wrapping NGSolve matrices to
3
+ PETSc matrices using the petsc4py interface.
4
+ '''
5
+ import numpy as np
6
+
7
+ from ngsolve import FESpace
8
+ from petsc4py import PETSc
9
+
10
+ class Matrix(object):
11
+ '''
12
+ This class creates a PETSc Matrix
13
+
14
+ :arg ngsMat: the NGSolve matrix
15
+
16
+ :arg freeDofs: free DOFs of the FE spaces used to construct the matrix
17
+
18
+ :arg matType: type of PETSc matrix, i.e. PETSc sparse: aij,
19
+ MKL sparse: aijmkl or CUDA: aijcusparse
20
+
21
+ '''
22
+ def __init__(self, ngsMat, parDescr, matType="aij", petscMat=None):
23
+ if not isinstance(parDescr, (tuple, list)):
24
+ samerc = True
25
+ if isinstance(parDescr, FESpace):
26
+ dofs = parDescr.ParallelDofs()
27
+ self.freeDofs = (parDescr.FreeDofs(),parDescr.FreeDofs())
28
+ comm = dofs.comm.mpi4py
29
+ else:
30
+ dofs, freeDofs, dofsInfo = parDescr
31
+ self.freeDofs = (freeDofs,freeDofs)
32
+ if dofs is not None:
33
+ comm = dofs.comm.mpi4py
34
+ else:
35
+ ### create suitable dofs
36
+ comm = PETSc.COMM_SELF
37
+ dofs = type('', (object,), {'entrysize':dofsInfo["bsize"][0]})()
38
+ else:
39
+ samerc = False
40
+ if isinstance(parDescr[0], FESpace) and isinstance(parDescr[1], FESpace):
41
+ dofs = parDescr[0].ParallelDofs()
42
+ self.freeDofs = (parDescr[0].FreeDofs(),parDescr[1].FreeDofs())
43
+ comm = dofs.comm.mpi4py
44
+ elif isinstance(parDescr[0], (tuple, list)):
45
+ dofs = parDescr[0][0]
46
+ self.freeDofs = (parDescr[0][1], parDescr[1][1])
47
+ if dofs is not None:
48
+ comm = dofs.comm.mpi4py
49
+ else:
50
+ ### create suitable dofs
51
+ comm = PETSc.COMM_SELF
52
+ else:
53
+ samerc = True
54
+ dofs = parDescr[0]
55
+ self.freeDofs = (parDescr[1], parDescr[1])
56
+ if dofs is not None:
57
+ comm = dofs.comm.mpi4py
58
+ else:
59
+ ### create suitable dofs
60
+ comm = PETSc.COMM_SELF
61
+
62
+ localMat = ngsMat.local_mat
63
+ entryHeight, entryWidth = localMat.entrysizes
64
+ if entryHeight != entryWidth: raise RuntimeError ("Only square entries are allowed.")
65
+
66
+ valMat, colMat, indMat = localMat.CSR()
67
+ indMat = np.array(indMat).astype(PETSc.IntType)
68
+ colMat = np.array(colMat).astype(PETSc.IntType)
69
+ if entryHeight > 1:
70
+ petscLocalMat = PETSc.Mat().createBAIJ(size=(entryHeight*localMat.height,
71
+ entryWidth*localMat.width),
72
+ bsize=entryHeight,
73
+ csr=(indMat,colMat,valMat),
74
+ comm=PETSc.COMM_SELF)
75
+ else:
76
+ petscLocalMat = PETSc.Mat().createAIJ(size=(localMat.height,
77
+ localMat.width),
78
+ csr=(indMat,colMat,valMat),
79
+ comm=PETSc.COMM_SELF)
80
+ if self.freeDofs[0] is not None or self.freeDofs[1] is not None:
81
+ rowIsFreeLocal = None
82
+ if self.freeDofs[0] is not None:
83
+ rowLocalMatFree = np.flatnonzero(self.freeDofs[0]).astype(PETSc.IntType)
84
+ rowIsFreeLocal = PETSc.IS().createBlock(indices=rowLocalMatFree,
85
+ bsize=entryHeight,comm=PETSc.COMM_SELF)
86
+ colIsFreeLocal = rowIsFreeLocal
87
+ if self.freeDofs[1] is not None and not samerc:
88
+ colLocalMatFree = np.flatnonzero(self.freeDofs[1]).astype(PETSc.IntType)
89
+ colIsFreeLocal = PETSc.IS().createBlock(indices=colLocalMatFree,
90
+ bsize=entryHeight,comm=PETSc.COMM_SELF)
91
+ petscLocalMat = petscLocalMat.createSubMatrices(rowIsFreeLocal, colIsFreeLocal)[0]
92
+
93
+ if comm.Get_size() > 1:
94
+ # is this a BUG in the bindings?
95
+ #rparallelDofs = ngsMat.row_pardofs
96
+ rparallelDofs = ngsMat.col_pardofs
97
+ rglobalNums, rnumberGlobal = rparallelDofs.EnumerateGlobally(self.freeDofs[0])
98
+ if self.freeDofs[0] is not None:
99
+ rglobalNums = np.array(rglobalNums, dtype=PETSc.IntType)[self.freeDofs[0]]
100
+ rlocalGlobalMap = PETSc.LGMap().create(indices=rglobalNums,
101
+ bsize=entryHeight,
102
+ comm=comm)
103
+ if not samerc:
104
+ # is this a BUG in the bindings?
105
+ #cparallelDofs = ngsMat.col_pardofs
106
+ cparallelDofs = ngsMat.row_pardofs
107
+ cglobalNums, cnumberGlobal = cparallelDofs.EnumerateGlobally(self.freeDofs[1])
108
+ if self.freeDofs[1] is not None:
109
+ cglobalNums = np.array(cglobalNums, dtype=PETSc.IntType)[self.freeDofs[1]]
110
+ clocalGlobalMap = PETSc.LGMap().create(indices=cglobalNums,
111
+ bsize=entryWidth,
112
+ comm=comm)
113
+ else:
114
+ clocalGlobalMap = rlocalGlobalMap
115
+ cnumberGlobal = rnumberGlobal
116
+
117
+ mat = PETSc.Mat().create(comm=comm)
118
+ mat.setSizes(size=(rnumberGlobal*entryHeight,
119
+ cnumberGlobal*entryHeight), bsize=entryHeight)
120
+ mat.setType(PETSc.Mat.Type.IS)
121
+ mat.setLGMap(rlocalGlobalMap, clocalGlobalMap)
122
+ mat.setISLocalMat(petscLocalMat)
123
+ mat.assemble()
124
+ if matType != 'is':
125
+ mat.convert(matType)
126
+ if petscMat is None:
127
+ self.mat = mat
128
+ else:
129
+ mat.copy(petscMat)
130
+ else:
131
+ mat = petscLocalMat
132
+ mat.convert(matType)
133
+ if matType != 'is':
134
+ mat.convert(matType)
135
+
136
+ if petscMat is None:
137
+ self.mat = mat
138
+ else:
139
+ mat.copy(petscMat)
140
+
141
+ def view(self):
142
+ '''
143
+ This function display PETSc Mat info
144
+
145
+ '''
146
+ self.mat.view()