1 /*
2 This is where the abstract matrix operations are defined
3 Portions of this code are under:
4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_CreateGraph;
40 PetscLogEvent MAT_SetValuesBatch;
41 PetscLogEvent MAT_ViennaCLCopyToGPU;
42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU;
43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
48
49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
50
51 /*@
52 MatSetRandom - Sets all components of a matrix to random numbers.
53
54 Logically Collective
55
56 Input Parameters:
57 + x - the matrix
58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
59 it will create one internally.
60
61 Example:
62 .vb
63 PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64 MatSetRandom(x,rctx);
65 PetscRandomDestroy(rctx);
66 .ve
67
68 Level: intermediate
69
70 Notes:
71 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations,
72
73 for sparse matrices that already have nonzero locations, it fills the locations with random numbers.
74
75 It generates an error if used on unassembled sparse matrices that have not been preallocated.
76
77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
78 @*/
MatSetRandom(Mat x,PetscRandom rctx)79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
80 {
81 PetscRandom randObj = NULL;
82
83 PetscFunctionBegin;
84 PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
85 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
86 PetscValidType(x, 1);
87 MatCheckPreallocated(x, 1);
88
89 if (!rctx) {
90 MPI_Comm comm;
91 PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
92 PetscCall(PetscRandomCreate(comm, &randObj));
93 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
94 PetscCall(PetscRandomSetFromOptions(randObj));
95 rctx = randObj;
96 }
97 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
98 PetscUseTypeMethod(x, setrandom, rctx);
99 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
100
101 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
102 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
103 PetscCall(PetscRandomDestroy(&randObj));
104 PetscFunctionReturn(PETSC_SUCCESS);
105 }
106
107 /*@
108 MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type
109
110 Logically Collective
111
112 Input Parameter:
113 . A - A matrix in unassembled, hash table form
114
115 Output Parameter:
116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()`
117
118 Example:
119 .vb
120 PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B));
121 PetscCall(MatCopyHashToXAIJ(A, B));
122 .ve
123
124 Level: advanced
125
126 Notes:
127 If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled
128
129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE`
130 @*/
MatCopyHashToXAIJ(Mat A,Mat B)131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B)
132 {
133 PetscFunctionBegin;
134 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
135 PetscUseTypeMethod(A, copyhashtoxaij, B);
136 PetscFunctionReturn(PETSC_SUCCESS);
137 }
138
139 /*@
140 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
141
142 Logically Collective
143
144 Input Parameter:
145 . mat - the factored matrix
146
147 Output Parameters:
148 + pivot - the pivot value computed
149 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
150 the share the matrix
151
152 Level: advanced
153
154 Notes:
155 This routine does not work for factorizations done with external packages.
156
157 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
158
159 This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
160
161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
163 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
164 @*/
MatFactorGetErrorZeroPivot(Mat mat,PetscReal * pivot,PetscInt * row)165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
166 {
167 PetscFunctionBegin;
168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
169 PetscAssertPointer(pivot, 2);
170 PetscAssertPointer(row, 3);
171 *pivot = mat->factorerror_zeropivot_value;
172 *row = mat->factorerror_zeropivot_row;
173 PetscFunctionReturn(PETSC_SUCCESS);
174 }
175
176 /*@
177 MatFactorGetError - gets the error code from a factorization
178
179 Logically Collective
180
181 Input Parameter:
182 . mat - the factored matrix
183
184 Output Parameter:
185 . err - the error code
186
187 Level: advanced
188
189 Note:
190 This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
191
192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
193 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
194 @*/
MatFactorGetError(Mat mat,MatFactorError * err)195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
196 {
197 PetscFunctionBegin;
198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
199 PetscAssertPointer(err, 2);
200 *err = mat->factorerrortype;
201 PetscFunctionReturn(PETSC_SUCCESS);
202 }
203
204 /*@
205 MatFactorClearError - clears the error code in a factorization
206
207 Logically Collective
208
209 Input Parameter:
210 . mat - the factored matrix
211
212 Level: developer
213
214 Note:
215 This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
216
217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
218 `MatGetErrorCode()`, `MatFactorError`
219 @*/
MatFactorClearError(Mat mat)220 PetscErrorCode MatFactorClearError(Mat mat)
221 {
222 PetscFunctionBegin;
223 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
224 mat->factorerrortype = MAT_FACTOR_NOERROR;
225 mat->factorerror_zeropivot_value = 0.0;
226 mat->factorerror_zeropivot_row = 0;
227 PetscFunctionReturn(PETSC_SUCCESS);
228 }
229
MatFindNonzeroRowsOrCols_Basic(Mat mat,PetscBool cols,PetscReal tol,IS * nonzero)230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
231 {
232 Vec r, l;
233 const PetscScalar *al;
234 PetscInt i, nz, gnz, N, n, st;
235
236 PetscFunctionBegin;
237 PetscCall(MatCreateVecs(mat, &r, &l));
238 if (!cols) { /* nonzero rows */
239 PetscCall(MatGetOwnershipRange(mat, &st, NULL));
240 PetscCall(MatGetSize(mat, &N, NULL));
241 PetscCall(MatGetLocalSize(mat, &n, NULL));
242 PetscCall(VecSet(l, 0.0));
243 PetscCall(VecSetRandom(r, NULL));
244 PetscCall(MatMult(mat, r, l));
245 PetscCall(VecGetArrayRead(l, &al));
246 } else { /* nonzero columns */
247 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL));
248 PetscCall(MatGetSize(mat, NULL, &N));
249 PetscCall(MatGetLocalSize(mat, NULL, &n));
250 PetscCall(VecSet(r, 0.0));
251 PetscCall(VecSetRandom(l, NULL));
252 PetscCall(MatMultTranspose(mat, l, r));
253 PetscCall(VecGetArrayRead(r, &al));
254 }
255 if (tol <= 0.0) {
256 for (i = 0, nz = 0; i < n; i++)
257 if (al[i] != 0.0) nz++;
258 } else {
259 for (i = 0, nz = 0; i < n; i++)
260 if (PetscAbsScalar(al[i]) > tol) nz++;
261 }
262 PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
263 if (gnz != N) {
264 PetscInt *nzr;
265 PetscCall(PetscMalloc1(nz, &nzr));
266 if (nz) {
267 if (tol < 0) {
268 for (i = 0, nz = 0; i < n; i++)
269 if (al[i] != 0.0) nzr[nz++] = i + st;
270 } else {
271 for (i = 0, nz = 0; i < n; i++)
272 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st;
273 }
274 }
275 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
276 } else *nonzero = NULL;
277 if (!cols) { /* nonzero rows */
278 PetscCall(VecRestoreArrayRead(l, &al));
279 } else {
280 PetscCall(VecRestoreArrayRead(r, &al));
281 }
282 PetscCall(VecDestroy(&l));
283 PetscCall(VecDestroy(&r));
284 PetscFunctionReturn(PETSC_SUCCESS);
285 }
286
287 /*@
288 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
289
290 Input Parameter:
291 . mat - the matrix
292
293 Output Parameter:
294 . keptrows - the rows that are not completely zero
295
296 Level: intermediate
297
298 Note:
299 `keptrows` is set to `NULL` if all rows are nonzero.
300
301 Developer Note:
302 If `keptrows` is not `NULL`, it must be sorted.
303
304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
305 @*/
MatFindNonzeroRows(Mat mat,IS * keptrows)306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
307 {
308 PetscFunctionBegin;
309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
310 PetscValidType(mat, 1);
311 PetscAssertPointer(keptrows, 2);
312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
313 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
314 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
315 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
316 if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE));
317 PetscFunctionReturn(PETSC_SUCCESS);
318 }
319
320 /*@
321 MatFindZeroRows - Locate all rows that are completely zero in the matrix
322
323 Input Parameter:
324 . mat - the matrix
325
326 Output Parameter:
327 . zerorows - the rows that are completely zero
328
329 Level: intermediate
330
331 Note:
332 `zerorows` is set to `NULL` if no rows are zero.
333
334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
335 @*/
MatFindZeroRows(Mat mat,IS * zerorows)336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
337 {
338 IS keptrows;
339 PetscInt m, n;
340
341 PetscFunctionBegin;
342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
343 PetscValidType(mat, 1);
344 PetscAssertPointer(zerorows, 2);
345 PetscCall(MatFindNonzeroRows(mat, &keptrows));
346 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
347 In keeping with this convention, we set zerorows to NULL if there are no zero
348 rows. */
349 if (keptrows == NULL) {
350 *zerorows = NULL;
351 } else {
352 PetscCall(MatGetOwnershipRange(mat, &m, &n));
353 PetscCall(ISComplement(keptrows, m, n, zerorows));
354 PetscCall(ISDestroy(&keptrows));
355 }
356 PetscFunctionReturn(PETSC_SUCCESS);
357 }
358
359 /*@
360 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
361
362 Not Collective
363
364 Input Parameter:
365 . A - the matrix
366
367 Output Parameter:
368 . a - the diagonal part (which is a SEQUENTIAL matrix)
369
370 Level: advanced
371
372 Notes:
373 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
374
375 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
376
377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
378 @*/
MatGetDiagonalBlock(Mat A,Mat * a)379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
380 {
381 PetscFunctionBegin;
382 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
383 PetscValidType(A, 1);
384 PetscAssertPointer(a, 2);
385 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
386 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
387 else {
388 PetscMPIInt size;
389
390 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
391 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
392 *a = A;
393 }
394 PetscFunctionReturn(PETSC_SUCCESS);
395 }
396
397 /*@
398 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
399
400 Collective
401
402 Input Parameter:
403 . mat - the matrix
404
405 Output Parameter:
406 . trace - the sum of the diagonal entries
407
408 Level: advanced
409
410 .seealso: [](ch_matrices), `Mat`
411 @*/
MatGetTrace(Mat mat,PetscScalar * trace)412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
413 {
414 Vec diag;
415
416 PetscFunctionBegin;
417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
418 PetscAssertPointer(trace, 2);
419 PetscCall(MatCreateVecs(mat, &diag, NULL));
420 PetscCall(MatGetDiagonal(mat, diag));
421 PetscCall(VecSum(diag, trace));
422 PetscCall(VecDestroy(&diag));
423 PetscFunctionReturn(PETSC_SUCCESS);
424 }
425
426 /*@
427 MatRealPart - Zeros out the imaginary part of the matrix
428
429 Logically Collective
430
431 Input Parameter:
432 . mat - the matrix
433
434 Level: advanced
435
436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
437 @*/
MatRealPart(Mat mat)438 PetscErrorCode MatRealPart(Mat mat)
439 {
440 PetscFunctionBegin;
441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
442 PetscValidType(mat, 1);
443 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
444 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
445 MatCheckPreallocated(mat, 1);
446 PetscUseTypeMethod(mat, realpart);
447 PetscFunctionReturn(PETSC_SUCCESS);
448 }
449
450 /*@C
451 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
452
453 Collective
454
455 Input Parameter:
456 . mat - the matrix
457
458 Output Parameters:
459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
460 - ghosts - the global indices of the ghost points
461
462 Level: advanced
463
464 Note:
465 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
466
467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
468 @*/
MatGetGhosts(Mat mat,PetscInt * nghosts,const PetscInt * ghosts[])469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
470 {
471 PetscFunctionBegin;
472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
473 PetscValidType(mat, 1);
474 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
475 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
476 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
477 else {
478 if (nghosts) *nghosts = 0;
479 if (ghosts) *ghosts = NULL;
480 }
481 PetscFunctionReturn(PETSC_SUCCESS);
482 }
483
484 /*@
485 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
486
487 Logically Collective
488
489 Input Parameter:
490 . mat - the matrix
491
492 Level: advanced
493
494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
495 @*/
MatImaginaryPart(Mat mat)496 PetscErrorCode MatImaginaryPart(Mat mat)
497 {
498 PetscFunctionBegin;
499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
500 PetscValidType(mat, 1);
501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
503 MatCheckPreallocated(mat, 1);
504 PetscUseTypeMethod(mat, imaginarypart);
505 PetscFunctionReturn(PETSC_SUCCESS);
506 }
507
508 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
509 /*@C
510 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()`
511 for each row that you get to ensure that your application does
512 not bleed memory.
513
514 Not Collective
515
516 Input Parameters:
517 + mat - the matrix
518 - row - the row to get
519
520 Output Parameters:
521 + ncols - if not `NULL`, the number of nonzeros in `row`
522 . cols - if not `NULL`, the column numbers
523 - vals - if not `NULL`, the numerical values
524
525 Level: advanced
526
527 Notes:
528 This routine is provided for people who need to have direct access
529 to the structure of a matrix. We hope that we provide enough
530 high-level matrix routines that few users will need it.
531
532 `MatGetRow()` always returns 0-based column indices, regardless of
533 whether the internal representation is 0-based (default) or 1-based.
534
535 For better efficiency, set `cols` and/or `vals` to `NULL` if you do
536 not wish to extract these quantities.
537
538 The user can only examine the values extracted with `MatGetRow()`;
539 the values CANNOT be altered. To change the matrix entries, one
540 must use `MatSetValues()`.
541
542 You can only have one call to `MatGetRow()` outstanding for a particular
543 matrix at a time, per processor. `MatGetRow()` can only obtain rows
544 associated with the given processor, it cannot get rows from the
545 other processors; for that we suggest using `MatCreateSubMatrices()`, then
546 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
547 is in the global number of rows.
548
549 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
550
551 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
552
553 Fortran Note:
554 .vb
555 PetscInt, pointer :: cols(:)
556 PetscScalar, pointer :: vals(:)
557 .ve
558
559 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
560 @*/
MatGetRow(Mat mat,PetscInt row,PetscInt * ncols,const PetscInt * cols[],const PetscScalar * vals[])561 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
562 {
563 PetscInt incols;
564
565 PetscFunctionBegin;
566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
567 PetscValidType(mat, 1);
568 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
569 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
570 MatCheckPreallocated(mat, 1);
571 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
572 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
573 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
574 if (ncols) *ncols = incols;
575 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
576 PetscFunctionReturn(PETSC_SUCCESS);
577 }
578
579 /*@
580 MatConjugate - replaces the matrix values with their complex conjugates
581
582 Logically Collective
583
584 Input Parameter:
585 . mat - the matrix
586
587 Level: advanced
588
589 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
590 @*/
MatConjugate(Mat mat)591 PetscErrorCode MatConjugate(Mat mat)
592 {
593 PetscFunctionBegin;
594 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
596 if (PetscDefined(USE_COMPLEX) && !(mat->symmetric == PETSC_BOOL3_TRUE && mat->hermitian == PETSC_BOOL3_TRUE)) {
597 PetscUseTypeMethod(mat, conjugate);
598 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
599 }
600 PetscFunctionReturn(PETSC_SUCCESS);
601 }
602
603 /*@C
604 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
605
606 Not Collective
607
608 Input Parameters:
609 + mat - the matrix
610 . row - the row to get
611 . ncols - the number of nonzeros
612 . cols - the columns of the nonzeros
613 - vals - if nonzero the column values
614
615 Level: advanced
616
617 Notes:
618 This routine should be called after you have finished examining the entries.
619
620 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
621 us of the array after it has been restored. If you pass `NULL`, it will
622 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
623
624 Fortran Note:
625 .vb
626 PetscInt, pointer :: cols(:)
627 PetscScalar, pointer :: vals(:)
628 .ve
629
630 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
631 @*/
MatRestoreRow(Mat mat,PetscInt row,PetscInt * ncols,const PetscInt * cols[],const PetscScalar * vals[])632 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
633 {
634 PetscFunctionBegin;
635 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
636 if (ncols) PetscAssertPointer(ncols, 3);
637 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
638 PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
639 if (ncols) *ncols = 0;
640 if (cols) *cols = NULL;
641 if (vals) *vals = NULL;
642 PetscFunctionReturn(PETSC_SUCCESS);
643 }
644
645 /*@
646 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
647 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
648
649 Not Collective
650
651 Input Parameter:
652 . mat - the matrix
653
654 Level: advanced
655
656 Note:
657 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
658
659 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
660 @*/
MatGetRowUpperTriangular(Mat mat)661 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
662 {
663 PetscFunctionBegin;
664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
665 PetscValidType(mat, 1);
666 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
667 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
668 MatCheckPreallocated(mat, 1);
669 PetscTryTypeMethod(mat, getrowuppertriangular);
670 PetscFunctionReturn(PETSC_SUCCESS);
671 }
672
673 /*@
674 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
675
676 Not Collective
677
678 Input Parameter:
679 . mat - the matrix
680
681 Level: advanced
682
683 Note:
684 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
685
686 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
687 @*/
MatRestoreRowUpperTriangular(Mat mat)688 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
689 {
690 PetscFunctionBegin;
691 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
692 PetscValidType(mat, 1);
693 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
694 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
695 MatCheckPreallocated(mat, 1);
696 PetscTryTypeMethod(mat, restorerowuppertriangular);
697 PetscFunctionReturn(PETSC_SUCCESS);
698 }
699
700 /*@
701 MatSetOptionsPrefix - Sets the prefix used for searching for all
702 `Mat` options in the database.
703
704 Logically Collective
705
706 Input Parameters:
707 + A - the matrix
708 - prefix - the prefix to prepend to all option names
709
710 Level: advanced
711
712 Notes:
713 A hyphen (-) must NOT be given at the beginning of the prefix name.
714 The first character of all runtime options is AUTOMATICALLY the hyphen.
715
716 This is NOT used for options for the factorization of the matrix. Normally the
717 prefix is automatically passed in from the PC calling the factorization. To set
718 it directly use `MatSetOptionsPrefixFactor()`
719
720 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
721 @*/
MatSetOptionsPrefix(Mat A,const char prefix[])722 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
723 {
724 PetscFunctionBegin;
725 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
726 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
727 PetscTryMethod(A, "MatSetOptionsPrefix_C", (Mat, const char[]), (A, prefix));
728 PetscFunctionReturn(PETSC_SUCCESS);
729 }
730
731 /*@
732 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
733 for matrices created with `MatGetFactor()`
734
735 Logically Collective
736
737 Input Parameters:
738 + A - the matrix
739 - prefix - the prefix to prepend to all option names for the factored matrix
740
741 Level: developer
742
743 Notes:
744 A hyphen (-) must NOT be given at the beginning of the prefix name.
745 The first character of all runtime options is AUTOMATICALLY the hyphen.
746
747 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
748 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()`
749
750 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
751 @*/
MatSetOptionsPrefixFactor(Mat A,const char prefix[])752 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
753 {
754 PetscFunctionBegin;
755 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
756 if (prefix) {
757 PetscAssertPointer(prefix, 2);
758 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
759 if (prefix != A->factorprefix) {
760 PetscCall(PetscFree(A->factorprefix));
761 PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
762 }
763 } else PetscCall(PetscFree(A->factorprefix));
764 PetscFunctionReturn(PETSC_SUCCESS);
765 }
766
767 /*@
768 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
769 for matrices created with `MatGetFactor()`
770
771 Logically Collective
772
773 Input Parameters:
774 + A - the matrix
775 - prefix - the prefix to prepend to all option names for the factored matrix
776
777 Level: developer
778
779 Notes:
780 A hyphen (-) must NOT be given at the beginning of the prefix name.
781 The first character of all runtime options is AUTOMATICALLY the hyphen.
782
783 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
784 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()`
785
786 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
787 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
788 `MatSetOptionsPrefix()`
789 @*/
MatAppendOptionsPrefixFactor(Mat A,const char prefix[])790 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
791 {
792 size_t len1, len2, new_len;
793
794 PetscFunctionBegin;
795 PetscValidHeader(A, 1);
796 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
797 if (!A->factorprefix) {
798 PetscCall(MatSetOptionsPrefixFactor(A, prefix));
799 PetscFunctionReturn(PETSC_SUCCESS);
800 }
801 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
802
803 PetscCall(PetscStrlen(A->factorprefix, &len1));
804 PetscCall(PetscStrlen(prefix, &len2));
805 new_len = len1 + len2 + 1;
806 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix));
807 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
808 PetscFunctionReturn(PETSC_SUCCESS);
809 }
810
811 /*@
812 MatAppendOptionsPrefix - Appends to the prefix used for searching for all
813 matrix options in the database.
814
815 Logically Collective
816
817 Input Parameters:
818 + A - the matrix
819 - prefix - the prefix to prepend to all option names
820
821 Level: advanced
822
823 Note:
824 A hyphen (-) must NOT be given at the beginning of the prefix name.
825 The first character of all runtime options is AUTOMATICALLY the hyphen.
826
827 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
828 @*/
MatAppendOptionsPrefix(Mat A,const char prefix[])829 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
830 {
831 PetscFunctionBegin;
832 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
833 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
834 PetscTryMethod(A, "MatAppendOptionsPrefix_C", (Mat, const char[]), (A, prefix));
835 PetscFunctionReturn(PETSC_SUCCESS);
836 }
837
838 /*@
839 MatGetOptionsPrefix - Gets the prefix used for searching for all
840 matrix options in the database.
841
842 Not Collective
843
844 Input Parameter:
845 . A - the matrix
846
847 Output Parameter:
848 . prefix - pointer to the prefix string used
849
850 Level: advanced
851
852 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
853 @*/
MatGetOptionsPrefix(Mat A,const char * prefix[])854 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
855 {
856 PetscFunctionBegin;
857 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
858 PetscAssertPointer(prefix, 2);
859 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
860 PetscFunctionReturn(PETSC_SUCCESS);
861 }
862
863 /*@
864 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()`
865
866 Not Collective
867
868 Input Parameter:
869 . A - the matrix
870
871 Output Parameter:
872 . state - the object state
873
874 Level: advanced
875
876 Note:
877 Object state is an integer which gets increased every time
878 the object is changed. By saving and later querying the object state
879 one can determine whether information about the object is still current.
880
881 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed.
882
883 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()`
884 @*/
MatGetState(Mat A,PetscObjectState * state)885 PetscErrorCode MatGetState(Mat A, PetscObjectState *state)
886 {
887 PetscFunctionBegin;
888 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
889 PetscAssertPointer(state, 2);
890 PetscCall(PetscObjectStateGet((PetscObject)A, state));
891 PetscFunctionReturn(PETSC_SUCCESS);
892 }
893
894 /*@
895 MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()`
896
897 Collective
898
899 Input Parameter:
900 . A - the matrix
901
902 Level: beginner
903
904 Notes:
905 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the
906 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()`
907 makes all of the preallocation space available
908
909 Current values in the matrix are lost in this call
910
911 Currently only supported for `MATAIJ` matrices.
912
913 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
914 @*/
MatResetPreallocation(Mat A)915 PetscErrorCode MatResetPreallocation(Mat A)
916 {
917 PetscFunctionBegin;
918 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
919 PetscValidType(A, 1);
920 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
921 PetscFunctionReturn(PETSC_SUCCESS);
922 }
923
924 /*@
925 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`.
926
927 Collective
928
929 Input Parameter:
930 . A - the matrix
931
932 Level: intermediate
933
934 Notes:
935 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
936
937 Currently only supported for `MATAIJ` matrices.
938
939 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()`
940 @*/
MatResetHash(Mat A)941 PetscErrorCode MatResetHash(Mat A)
942 {
943 PetscFunctionBegin;
944 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
945 PetscValidType(A, 1);
946 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset to hash state after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()");
947 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
948 PetscUseMethod(A, "MatResetHash_C", (Mat), (A));
949 /* These flags are used to determine whether certain setups occur */
950 A->was_assembled = PETSC_FALSE;
951 A->assembled = PETSC_FALSE;
952 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */
953 PetscCall(PetscObjectStateIncrease((PetscObject)A));
954 PetscFunctionReturn(PETSC_SUCCESS);
955 }
956
957 /*@
958 MatSetUp - Sets up the internal matrix data structures for later use by the matrix
959
960 Collective
961
962 Input Parameter:
963 . A - the matrix
964
965 Level: advanced
966
967 Notes:
968 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
969 setting values in the matrix.
970
971 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users
972
973 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
974 @*/
MatSetUp(Mat A)975 PetscErrorCode MatSetUp(Mat A)
976 {
977 PetscFunctionBegin;
978 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
979 if (!((PetscObject)A)->type_name) {
980 PetscMPIInt size;
981
982 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
983 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
984 }
985 if (!A->preallocated) PetscTryTypeMethod(A, setup);
986 PetscCall(PetscLayoutSetUp(A->rmap));
987 PetscCall(PetscLayoutSetUp(A->cmap));
988 A->preallocated = PETSC_TRUE;
989 PetscFunctionReturn(PETSC_SUCCESS);
990 }
991
992 #if defined(PETSC_HAVE_SAWS)
993 #include <petscviewersaws.h>
994 #endif
995
996 /*
997 If threadsafety is on extraneous matrices may be printed
998
999 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
1000 */
1001 #if !defined(PETSC_HAVE_THREADSAFETY)
1002 static PetscInt insidematview = 0;
1003 #endif
1004
1005 /*@
1006 MatViewFromOptions - View properties of the matrix based on options set in the options database
1007
1008 Collective
1009
1010 Input Parameters:
1011 + A - the matrix
1012 . obj - optional additional object that provides the options prefix to use
1013 - name - command line option
1014
1015 Options Database Key:
1016 . -mat_view [viewertype]:... - the viewer and its options
1017
1018 Level: intermediate
1019
1020 Note:
1021 .vb
1022 If no value is provided ascii:stdout is used
1023 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
1024 for example ascii::ascii_info prints just the information about the object not all details
1025 unless :append is given filename opens in write mode, overwriting what was already there
1026 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput
1027 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x
1028 socket[:port] defaults to the standard output port
1029 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs)
1030 .ve
1031
1032 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1033 @*/
MatViewFromOptions(Mat A,PetscObject obj,const char name[])1034 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1035 {
1036 PetscFunctionBegin;
1037 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1038 #if !defined(PETSC_HAVE_THREADSAFETY)
1039 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1040 #endif
1041 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1042 PetscFunctionReturn(PETSC_SUCCESS);
1043 }
1044
1045 /*@
1046 MatView - display information about a matrix in a variety ways
1047
1048 Collective on viewer
1049
1050 Input Parameters:
1051 + mat - the matrix
1052 - viewer - visualization context
1053
1054 Options Database Keys:
1055 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1056 . -mat_view ::ascii_info_detail - Prints more detailed info
1057 . -mat_view - Prints matrix in ASCII format
1058 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format
1059 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1060 . -display <name> - Sets display name (default is host)
1061 . -draw_pause <sec> - Sets number of seconds to pause after display
1062 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1063 . -viewer_socket_machine <machine> - -
1064 . -viewer_socket_port <port> - -
1065 . -mat_view binary - save matrix to file in binary format
1066 - -viewer_binary_filename <name> - -
1067
1068 Level: beginner
1069
1070 Notes:
1071 The available visualization contexts include
1072 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1073 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1074 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1075 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1076
1077 The user can open alternative visualization contexts with
1078 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1079 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()`
1080 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display
1081 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer.
1082
1083 The user can call `PetscViewerPushFormat()` to specify the output
1084 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1085 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include
1086 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1087 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1088 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1089 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types
1090 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default)
1091 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries)
1092 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries)
1093
1094 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1095 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1096
1097 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1098
1099 See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1100 viewer is used.
1101
1102 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1103 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1104
1105 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1106 and then use the following mouse functions.
1107 .vb
1108 left mouse: zoom in
1109 middle mouse: zoom out
1110 right mouse: continue with the simulation
1111 .ve
1112
1113 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1114 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1115 @*/
MatView(Mat mat,PetscViewer viewer)1116 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1117 {
1118 PetscInt rows, cols, rbs, cbs;
1119 PetscBool isascii, isstring, issaws;
1120 PetscViewerFormat format;
1121 PetscMPIInt size;
1122
1123 PetscFunctionBegin;
1124 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1125 PetscValidType(mat, 1);
1126 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1127 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1128
1129 PetscCall(PetscViewerGetFormat(viewer, &format));
1130 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1131 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1132
1133 #if !defined(PETSC_HAVE_THREADSAFETY)
1134 insidematview++;
1135 #endif
1136 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1137 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1138 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1139 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1140
1141 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1142 if (isascii) {
1143 if (!mat->preallocated) {
1144 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1145 #if !defined(PETSC_HAVE_THREADSAFETY)
1146 insidematview--;
1147 #endif
1148 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1149 PetscFunctionReturn(PETSC_SUCCESS);
1150 }
1151 if (!mat->assembled) {
1152 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1153 #if !defined(PETSC_HAVE_THREADSAFETY)
1154 insidematview--;
1155 #endif
1156 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1157 PetscFunctionReturn(PETSC_SUCCESS);
1158 }
1159 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1160 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1161 MatNullSpace nullsp, transnullsp;
1162
1163 PetscCall(PetscViewerASCIIPushTab(viewer));
1164 PetscCall(MatGetSize(mat, &rows, &cols));
1165 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1166 if (rbs != 1 || cbs != 1) {
1167 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "%s\n", rows, cols, rbs, cbs, mat->bsizes ? " variable blocks set" : ""));
1168 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1169 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1170 if (mat->factortype) {
1171 MatSolverType solver;
1172 PetscCall(MatFactorGetSolverType(mat, &solver));
1173 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1174 }
1175 if (mat->ops->getinfo) {
1176 PetscBool is_constant_or_diagonal;
1177
1178 // Don't print nonzero information for constant or diagonal matrices, it just adds noise to the output
1179 PetscCall(PetscObjectTypeCompareAny((PetscObject)mat, &is_constant_or_diagonal, MATCONSTANTDIAGONAL, MATDIAGONAL, ""));
1180 if (!is_constant_or_diagonal) {
1181 MatInfo info;
1182
1183 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1184 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1185 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1186 }
1187 }
1188 PetscCall(MatGetNullSpace(mat, &nullsp));
1189 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1190 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n"));
1191 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n"));
1192 PetscCall(MatGetNearNullSpace(mat, &nullsp));
1193 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n"));
1194 PetscCall(PetscViewerASCIIPushTab(viewer));
1195 PetscCall(MatProductView(mat, viewer));
1196 PetscCall(PetscViewerASCIIPopTab(viewer));
1197 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1198 IS tmp;
1199
1200 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1201 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1202 PetscCall(PetscViewerASCIIPushTab(viewer));
1203 PetscCall(ISView(tmp, viewer));
1204 PetscCall(PetscViewerASCIIPopTab(viewer));
1205 PetscCall(ISDestroy(&tmp));
1206 }
1207 }
1208 } else if (issaws) {
1209 #if defined(PETSC_HAVE_SAWS)
1210 PetscMPIInt rank;
1211
1212 PetscCall(PetscObjectName((PetscObject)mat));
1213 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1214 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1215 #endif
1216 } else if (isstring) {
1217 const char *type;
1218 PetscCall(MatGetType(mat, &type));
1219 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1220 PetscTryTypeMethod(mat, view, viewer);
1221 }
1222 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1223 PetscCall(PetscViewerASCIIPushTab(viewer));
1224 PetscUseTypeMethod(mat, viewnative, viewer);
1225 PetscCall(PetscViewerASCIIPopTab(viewer));
1226 } else if (mat->ops->view) {
1227 PetscCall(PetscViewerASCIIPushTab(viewer));
1228 PetscUseTypeMethod(mat, view, viewer);
1229 PetscCall(PetscViewerASCIIPopTab(viewer));
1230 }
1231 if (isascii) {
1232 PetscCall(PetscViewerGetFormat(viewer, &format));
1233 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1234 }
1235 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1236 #if !defined(PETSC_HAVE_THREADSAFETY)
1237 insidematview--;
1238 #endif
1239 PetscFunctionReturn(PETSC_SUCCESS);
1240 }
1241
1242 #if defined(PETSC_USE_DEBUG)
1243 #include <../src/sys/totalview/tv_data_display.h>
TV_display_type(const struct _p_Mat * mat)1244 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1245 {
1246 TV_add_row("Local rows", "int", &mat->rmap->n);
1247 TV_add_row("Local columns", "int", &mat->cmap->n);
1248 TV_add_row("Global rows", "int", &mat->rmap->N);
1249 TV_add_row("Global columns", "int", &mat->cmap->N);
1250 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1251 return TV_format_OK;
1252 }
1253 #endif
1254
1255 /*@
1256 MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1257 with `MatView()`. The matrix format is determined from the options database.
1258 Generates a parallel MPI matrix if the communicator has more than one
1259 processor. The default matrix type is `MATAIJ`.
1260
1261 Collective
1262
1263 Input Parameters:
1264 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1265 or some related function before a call to `MatLoad()`
1266 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1267
1268 Options Database Key:
1269 . -matload_block_size <bs> - set block size
1270
1271 Level: beginner
1272
1273 Notes:
1274 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1275 `Mat` before calling this routine if you wish to set it from the options database.
1276
1277 `MatLoad()` automatically loads into the options database any options
1278 given in the file filename.info where filename is the name of the file
1279 that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1280 file will be ignored if you use the -viewer_binary_skip_info option.
1281
1282 If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1283 sets the default matrix type AIJ and sets the local and global sizes.
1284 If type and/or size is already set, then the same are used.
1285
1286 In parallel, each processor can load a subset of rows (or the
1287 entire matrix). This routine is especially useful when a large
1288 matrix is stored on disk and only part of it is desired on each
1289 processor. For example, a parallel solver may access only some of
1290 the rows from each processor. The algorithm used here reads
1291 relatively small blocks of data rather than reading the entire
1292 matrix and then subsetting it.
1293
1294 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1295 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1296 or the sequence like
1297 .vb
1298 `PetscViewer` v;
1299 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1300 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1301 `PetscViewerSetFromOptions`(v);
1302 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1303 `PetscViewerFileSetName`(v,"datafile");
1304 .ve
1305 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1306 .vb
1307 -viewer_type {binary, hdf5}
1308 .ve
1309
1310 See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1311 and src/mat/tutorials/ex10.c with the second approach.
1312
1313 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1314 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1315 Multiple objects, both matrices and vectors, can be stored within the same file.
1316 Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1317
1318 Most users should not need to know the details of the binary storage
1319 format, since `MatLoad()` and `MatView()` completely hide these details.
1320 But for anyone who is interested, the standard binary matrix storage
1321 format is
1322
1323 .vb
1324 PetscInt MAT_FILE_CLASSID
1325 PetscInt number of rows
1326 PetscInt number of columns
1327 PetscInt total number of nonzeros
1328 PetscInt *number nonzeros in each row
1329 PetscInt *column indices of all nonzeros (starting index is zero)
1330 PetscScalar *values of all nonzeros
1331 .ve
1332 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1333 stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this
1334 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1335
1336 PETSc automatically does the byte swapping for
1337 machines that store the bytes reversed. Thus if you write your own binary
1338 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1339 and `PetscBinaryWrite()` to see how this may be done.
1340
1341 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1342 Each processor's chunk is loaded independently by its owning MPI process.
1343 Multiple objects, both matrices and vectors, can be stored within the same file.
1344 They are looked up by their PetscObject name.
1345
1346 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1347 by default the same structure and naming of the AIJ arrays and column count
1348 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1349 .vb
1350 save example.mat A b -v7.3
1351 .ve
1352 can be directly read by this routine (see Reference 1 for details).
1353
1354 Depending on your MATLAB version, this format might be a default,
1355 otherwise you can set it as default in Preferences.
1356
1357 Unless -nocompression flag is used to save the file in MATLAB,
1358 PETSc must be configured with ZLIB package.
1359
1360 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1361
1362 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1363
1364 Corresponding `MatView()` is not yet implemented.
1365
1366 The loaded matrix is actually a transpose of the original one in MATLAB,
1367 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1368 With this format, matrix is automatically transposed by PETSc,
1369 unless the matrix is marked as SPD or symmetric
1370 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1371
1372 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1373
1374 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1375 @*/
MatLoad(Mat mat,PetscViewer viewer)1376 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1377 {
1378 PetscBool flg;
1379
1380 PetscFunctionBegin;
1381 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1382 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1383
1384 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1385
1386 flg = PETSC_FALSE;
1387 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1388 if (flg) {
1389 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1390 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1391 }
1392 flg = PETSC_FALSE;
1393 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1394 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1395
1396 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1397 PetscUseTypeMethod(mat, load, viewer);
1398 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1399 PetscFunctionReturn(PETSC_SUCCESS);
1400 }
1401
MatDestroy_Redundant(Mat_Redundant ** redundant)1402 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1403 {
1404 Mat_Redundant *redund = *redundant;
1405
1406 PetscFunctionBegin;
1407 if (redund) {
1408 if (redund->matseq) { /* via MatCreateSubMatrices() */
1409 PetscCall(ISDestroy(&redund->isrow));
1410 PetscCall(ISDestroy(&redund->iscol));
1411 PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1412 } else {
1413 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1414 PetscCall(PetscFree(redund->sbuf_j));
1415 PetscCall(PetscFree(redund->sbuf_a));
1416 for (PetscInt i = 0; i < redund->nrecvs; i++) {
1417 PetscCall(PetscFree(redund->rbuf_j[i]));
1418 PetscCall(PetscFree(redund->rbuf_a[i]));
1419 }
1420 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1421 }
1422
1423 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1424 PetscCall(PetscFree(redund));
1425 }
1426 PetscFunctionReturn(PETSC_SUCCESS);
1427 }
1428
1429 /*@
1430 MatDestroy - Frees space taken by a matrix.
1431
1432 Collective
1433
1434 Input Parameter:
1435 . A - the matrix
1436
1437 Level: beginner
1438
1439 Developer Note:
1440 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1441 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1442 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1443 if changes are needed here.
1444
1445 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1446 @*/
MatDestroy(Mat * A)1447 PetscErrorCode MatDestroy(Mat *A)
1448 {
1449 PetscFunctionBegin;
1450 if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1451 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1452 if (--((PetscObject)*A)->refct > 0) {
1453 *A = NULL;
1454 PetscFunctionReturn(PETSC_SUCCESS);
1455 }
1456
1457 /* if memory was published with SAWs then destroy it */
1458 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1459 PetscTryTypeMethod(*A, destroy);
1460
1461 PetscCall(PetscFree((*A)->factorprefix));
1462 PetscCall(PetscFree((*A)->defaultvectype));
1463 PetscCall(PetscFree((*A)->defaultrandtype));
1464 PetscCall(PetscFree((*A)->bsizes));
1465 PetscCall(PetscFree((*A)->solvertype));
1466 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1467 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1468 PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1469 PetscCall(MatProductClear(*A));
1470 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1471 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1472 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1473 PetscCall(MatDestroy(&(*A)->schur));
1474 PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1475 PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1476 PetscCall(PetscHeaderDestroy(A));
1477 PetscFunctionReturn(PETSC_SUCCESS);
1478 }
1479
1480 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1481 /*@
1482 MatSetValues - Inserts or adds a block of values into a matrix.
1483 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1484 MUST be called after all calls to `MatSetValues()` have been completed.
1485
1486 Not Collective
1487
1488 Input Parameters:
1489 + mat - the matrix
1490 . m - the number of rows
1491 . idxm - the global indices of the rows
1492 . n - the number of columns
1493 . idxn - the global indices of the columns
1494 . v - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order.
1495 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
1496 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1497
1498 Level: beginner
1499
1500 Notes:
1501 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1502 options cannot be mixed without intervening calls to the assembly
1503 routines.
1504
1505 `MatSetValues()` uses 0-based row and column numbers in Fortran
1506 as well as in C.
1507
1508 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1509 simply ignored. This allows easily inserting element stiffness matrices
1510 with homogeneous Dirichlet boundary conditions that you don't want represented
1511 in the matrix.
1512
1513 Efficiency Alert:
1514 The routine `MatSetValuesBlocked()` may offer much better efficiency
1515 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1516
1517 Fortran Notes:
1518 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1519 .vb
1520 call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr)
1521 .ve
1522
1523 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1524
1525 Developer Note:
1526 This is labeled with C so does not automatically generate Fortran stubs and interfaces
1527 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1528
1529 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1530 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1531 @*/
MatSetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)1532 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1533 {
1534 PetscFunctionBeginHot;
1535 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1536 PetscValidType(mat, 1);
1537 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1538 PetscAssertPointer(idxm, 3);
1539 PetscAssertPointer(idxn, 5);
1540 MatCheckPreallocated(mat, 1);
1541
1542 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1543 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1544
1545 if (PetscDefined(USE_DEBUG)) {
1546 PetscInt i, j;
1547
1548 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1549 if (v) {
1550 for (i = 0; i < m; i++) {
1551 for (j = 0; j < n; j++) {
1552 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1553 #if defined(PETSC_USE_COMPLEX)
1554 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1555 #else
1556 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1557 #endif
1558 }
1559 }
1560 }
1561 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1562 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1563 }
1564
1565 if (mat->assembled) {
1566 mat->was_assembled = PETSC_TRUE;
1567 mat->assembled = PETSC_FALSE;
1568 }
1569 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1570 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1571 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1572 PetscFunctionReturn(PETSC_SUCCESS);
1573 }
1574
1575 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1576 /*@
1577 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1578 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1579 MUST be called after all calls to `MatSetValues()` have been completed.
1580
1581 Not Collective
1582
1583 Input Parameters:
1584 + mat - the matrix
1585 . ism - the rows to provide
1586 . isn - the columns to provide
1587 . v - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order.
1588 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
1589 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1590
1591 Level: beginner
1592
1593 Notes:
1594 By default, the values, `v`, are stored in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
1595
1596 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1597 options cannot be mixed without intervening calls to the assembly
1598 routines.
1599
1600 `MatSetValues()` uses 0-based row and column numbers in Fortran
1601 as well as in C.
1602
1603 Negative indices may be passed in `ism` and `isn`, these rows and columns are
1604 simply ignored. This allows easily inserting element stiffness matrices
1605 with homogeneous Dirichlet boundary conditions that you don't want represented
1606 in the matrix.
1607
1608 Fortran Note:
1609 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1610
1611 Efficiency Alert:
1612 The routine `MatSetValuesBlocked()` may offer much better efficiency
1613 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1614
1615 This is currently not optimized for any particular `ISType`
1616
1617 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1618 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1619 @*/
MatSetValuesIS(Mat mat,IS ism,IS isn,const PetscScalar v[],InsertMode addv)1620 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1621 {
1622 PetscInt m, n;
1623 const PetscInt *rows, *cols;
1624
1625 PetscFunctionBeginHot;
1626 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1627 PetscCall(ISGetIndices(ism, &rows));
1628 PetscCall(ISGetIndices(isn, &cols));
1629 PetscCall(ISGetLocalSize(ism, &m));
1630 PetscCall(ISGetLocalSize(isn, &n));
1631 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1632 PetscCall(ISRestoreIndices(ism, &rows));
1633 PetscCall(ISRestoreIndices(isn, &cols));
1634 PetscFunctionReturn(PETSC_SUCCESS);
1635 }
1636
1637 /*@
1638 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1639 values into a matrix
1640
1641 Not Collective
1642
1643 Input Parameters:
1644 + mat - the matrix
1645 . row - the (block) row to set
1646 - v - a one-dimensional array that contains the values. For `MATBAIJ` they are implicitly stored as a two-dimensional array, by default in row-major order.
1647 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
1648
1649 Level: intermediate
1650
1651 Notes:
1652 The values, `v`, are column-oriented (for the block version) and sorted
1653
1654 All the nonzero values in `row` must be provided
1655
1656 The matrix must have previously had its column indices set, likely by having been assembled.
1657
1658 `row` must belong to this MPI process
1659
1660 Fortran Note:
1661 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1662
1663 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1664 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1665 @*/
MatSetValuesRowLocal(Mat mat,PetscInt row,const PetscScalar v[])1666 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1667 {
1668 PetscInt globalrow;
1669
1670 PetscFunctionBegin;
1671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1672 PetscValidType(mat, 1);
1673 PetscAssertPointer(v, 3);
1674 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1675 PetscCall(MatSetValuesRow(mat, globalrow, v));
1676 PetscFunctionReturn(PETSC_SUCCESS);
1677 }
1678
1679 /*@
1680 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1681 values into a matrix
1682
1683 Not Collective
1684
1685 Input Parameters:
1686 + mat - the matrix
1687 . row - the (block) row to set
1688 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values
1689
1690 Level: advanced
1691
1692 Notes:
1693 The values, `v`, are column-oriented for the block version.
1694
1695 All the nonzeros in `row` must be provided
1696
1697 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1698
1699 `row` must belong to this process
1700
1701 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1702 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1703 @*/
MatSetValuesRow(Mat mat,PetscInt row,const PetscScalar v[])1704 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1705 {
1706 PetscFunctionBeginHot;
1707 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1708 PetscValidType(mat, 1);
1709 MatCheckPreallocated(mat, 1);
1710 PetscAssertPointer(v, 3);
1711 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1712 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1713 mat->insertmode = INSERT_VALUES;
1714
1715 if (mat->assembled) {
1716 mat->was_assembled = PETSC_TRUE;
1717 mat->assembled = PETSC_FALSE;
1718 }
1719 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1720 PetscUseTypeMethod(mat, setvaluesrow, row, v);
1721 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1722 PetscFunctionReturn(PETSC_SUCCESS);
1723 }
1724
1725 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1726 /*@
1727 MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1728 Using structured grid indexing
1729
1730 Not Collective
1731
1732 Input Parameters:
1733 + mat - the matrix
1734 . m - number of rows being entered
1735 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1736 . n - number of columns being entered
1737 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1738 . v - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order.
1739 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
1740 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1741
1742 Level: beginner
1743
1744 Notes:
1745 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options.
1746
1747 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1748 options cannot be mixed without intervening calls to the assembly
1749 routines.
1750
1751 The grid coordinates are across the entire grid, not just the local portion
1752
1753 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1754 as well as in C.
1755
1756 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1757
1758 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1759 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1760
1761 The columns and rows in the stencil passed in MUST be contained within the
1762 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1763 if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1764 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1765 first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1766
1767 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1768 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1769 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1770 `DM_BOUNDARY_PERIODIC` boundary type.
1771
1772 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1773 a single value per point) you can skip filling those indices.
1774
1775 Inspired by the structured grid interface to the HYPRE package
1776 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1777
1778 Fortran Note:
1779 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1780
1781 Efficiency Alert:
1782 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1783 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1784
1785 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1786 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1787 @*/
MatSetValuesStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)1788 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1789 {
1790 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1791 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1792 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1793
1794 PetscFunctionBegin;
1795 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1796 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1797 PetscValidType(mat, 1);
1798 PetscAssertPointer(idxm, 3);
1799 PetscAssertPointer(idxn, 5);
1800
1801 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1802 jdxm = buf;
1803 jdxn = buf + m;
1804 } else {
1805 PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1806 jdxm = bufm;
1807 jdxn = bufn;
1808 }
1809 for (i = 0; i < m; i++) {
1810 for (j = 0; j < 3 - sdim; j++) dxm++;
1811 tmp = *dxm++ - starts[0];
1812 for (j = 0; j < dim - 1; j++) {
1813 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1814 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1815 }
1816 if (mat->stencil.noc) dxm++;
1817 jdxm[i] = tmp;
1818 }
1819 for (i = 0; i < n; i++) {
1820 for (j = 0; j < 3 - sdim; j++) dxn++;
1821 tmp = *dxn++ - starts[0];
1822 for (j = 0; j < dim - 1; j++) {
1823 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1824 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1825 }
1826 if (mat->stencil.noc) dxn++;
1827 jdxn[i] = tmp;
1828 }
1829 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1830 PetscCall(PetscFree2(bufm, bufn));
1831 PetscFunctionReturn(PETSC_SUCCESS);
1832 }
1833
1834 /*@
1835 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1836 Using structured grid indexing
1837
1838 Not Collective
1839
1840 Input Parameters:
1841 + mat - the matrix
1842 . m - number of rows being entered
1843 . idxm - grid coordinates for matrix rows being entered
1844 . n - number of columns being entered
1845 . idxn - grid coordinates for matrix columns being entered
1846 . v - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order.
1847 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
1848 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1849
1850 Level: beginner
1851
1852 Notes:
1853 By default the values, `v`, are row-oriented and unsorted.
1854 See `MatSetOption()` for other options.
1855
1856 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1857 options cannot be mixed without intervening calls to the assembly
1858 routines.
1859
1860 The grid coordinates are across the entire grid, not just the local portion
1861
1862 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1863 as well as in C.
1864
1865 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1866
1867 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1868 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1869
1870 The columns and rows in the stencil passed in MUST be contained within the
1871 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1872 if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1873 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1874 first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1875
1876 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1877 simply ignored. This allows easily inserting element stiffness matrices
1878 with homogeneous Dirichlet boundary conditions that you don't want represented
1879 in the matrix.
1880
1881 Inspired by the structured grid interface to the HYPRE package
1882 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1883
1884 Fortran Notes:
1885 `idxm` and `idxn` should be declared as
1886 .vb
1887 MatStencil idxm(4,m),idxn(4,n)
1888 .ve
1889 and the values inserted using
1890 .vb
1891 idxm(MatStencil_i,1) = i
1892 idxm(MatStencil_j,1) = j
1893 idxm(MatStencil_k,1) = k
1894 etc
1895 .ve
1896
1897 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1898
1899 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1900 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1901 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1902 @*/
MatSetValuesBlockedStencil(Mat mat,PetscInt m,const MatStencil idxm[],PetscInt n,const MatStencil idxn[],const PetscScalar v[],InsertMode addv)1903 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1904 {
1905 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1906 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1907 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1908
1909 PetscFunctionBegin;
1910 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1911 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1912 PetscValidType(mat, 1);
1913 PetscAssertPointer(idxm, 3);
1914 PetscAssertPointer(idxn, 5);
1915 PetscAssertPointer(v, 6);
1916
1917 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1918 jdxm = buf;
1919 jdxn = buf + m;
1920 } else {
1921 PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1922 jdxm = bufm;
1923 jdxn = bufn;
1924 }
1925 for (i = 0; i < m; i++) {
1926 for (j = 0; j < 3 - sdim; j++) dxm++;
1927 tmp = *dxm++ - starts[0];
1928 for (j = 0; j < sdim - 1; j++) {
1929 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1930 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1931 }
1932 dxm++;
1933 jdxm[i] = tmp;
1934 }
1935 for (i = 0; i < n; i++) {
1936 for (j = 0; j < 3 - sdim; j++) dxn++;
1937 tmp = *dxn++ - starts[0];
1938 for (j = 0; j < sdim - 1; j++) {
1939 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1940 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1941 }
1942 dxn++;
1943 jdxn[i] = tmp;
1944 }
1945 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1946 PetscCall(PetscFree2(bufm, bufn));
1947 PetscFunctionReturn(PETSC_SUCCESS);
1948 }
1949
1950 /*@
1951 MatSetStencil - Sets the grid information for setting values into a matrix via
1952 `MatSetValuesStencil()`
1953
1954 Not Collective
1955
1956 Input Parameters:
1957 + mat - the matrix
1958 . dim - dimension of the grid 1, 2, or 3
1959 . dims - number of grid points in x, y, and z direction, including ghost points on your processor
1960 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1961 - dof - number of degrees of freedom per node
1962
1963 Level: beginner
1964
1965 Notes:
1966 Inspired by the structured grid interface to the HYPRE package
1967 (www.llnl.gov/CASC/hyper)
1968
1969 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1970 user.
1971
1972 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1973 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1974 @*/
MatSetStencil(Mat mat,PetscInt dim,const PetscInt dims[],const PetscInt starts[],PetscInt dof)1975 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1976 {
1977 PetscFunctionBegin;
1978 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1979 PetscAssertPointer(dims, 3);
1980 PetscAssertPointer(starts, 4);
1981
1982 mat->stencil.dim = dim + (dof > 1);
1983 for (PetscInt i = 0; i < dim; i++) {
1984 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */
1985 mat->stencil.starts[i] = starts[dim - i - 1];
1986 }
1987 mat->stencil.dims[dim] = dof;
1988 mat->stencil.starts[dim] = 0;
1989 mat->stencil.noc = (PetscBool)(dof == 1);
1990 PetscFunctionReturn(PETSC_SUCCESS);
1991 }
1992
1993 /*@
1994 MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1995
1996 Not Collective
1997
1998 Input Parameters:
1999 + mat - the matrix
2000 . m - the number of block rows
2001 . idxm - the global block indices
2002 . n - the number of block columns
2003 . idxn - the global block indices
2004 . v - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order.
2005 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
2006 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
2007
2008 Level: intermediate
2009
2010 Notes:
2011 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
2012 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
2013
2014 The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
2015 NOT the total number of rows/columns; for example, if the block size is 2 and
2016 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4).
2017 The values in `idxm` would be 1 2; that is the first index for each block divided by
2018 the block size.
2019
2020 You must call `MatSetBlockSize()` when constructing this matrix (before
2021 preallocating it).
2022
2023 By default, the values, `v`, are stored in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
2024
2025 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
2026 options cannot be mixed without intervening calls to the assembly
2027 routines.
2028
2029 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
2030 as well as in C.
2031
2032 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
2033 simply ignored. This allows easily inserting element stiffness matrices
2034 with homogeneous Dirichlet boundary conditions that you don't want represented
2035 in the matrix.
2036
2037 Each time an entry is set within a sparse matrix via `MatSetValues()`,
2038 internal searching must be done to determine where to place the
2039 data in the matrix storage space. By instead inserting blocks of
2040 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2041 reduced.
2042
2043 Example:
2044 .vb
2045 Suppose m=n=2 and block size(bs) = 2 The array is
2046
2047 1 2 | 3 4
2048 5 6 | 7 8
2049 - - - | - - -
2050 9 10 | 11 12
2051 13 14 | 15 16
2052
2053 v[] should be passed in like
2054 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2055
2056 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2057 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2058 .ve
2059
2060 Fortran Notes:
2061 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example,
2062 .vb
2063 call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr)
2064 .ve
2065
2066 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2067
2068 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2069 @*/
MatSetValuesBlocked(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)2070 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2071 {
2072 PetscFunctionBeginHot;
2073 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2074 PetscValidType(mat, 1);
2075 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2076 PetscAssertPointer(idxm, 3);
2077 PetscAssertPointer(idxn, 5);
2078 MatCheckPreallocated(mat, 1);
2079 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2080 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2081 if (PetscDefined(USE_DEBUG)) {
2082 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2083 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2084 }
2085 if (PetscDefined(USE_DEBUG)) {
2086 PetscInt rbs, cbs, M, N, i;
2087 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2088 PetscCall(MatGetSize(mat, &M, &N));
2089 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than row length %" PetscInt_FMT, i, idxm[i], rbs, M);
2090 for (i = 0; i < n; i++)
2091 PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than column length %" PetscInt_FMT, i, idxn[i], cbs, N);
2092 }
2093 if (mat->assembled) {
2094 mat->was_assembled = PETSC_TRUE;
2095 mat->assembled = PETSC_FALSE;
2096 }
2097 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2098 if (mat->ops->setvaluesblocked) {
2099 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2100 } else {
2101 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2102 PetscInt i, j, bs, cbs;
2103
2104 PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2105 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2106 iidxm = buf;
2107 iidxn = buf + m * bs;
2108 } else {
2109 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2110 iidxm = bufr;
2111 iidxn = bufc;
2112 }
2113 for (i = 0; i < m; i++) {
2114 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2115 }
2116 if (m != n || bs != cbs || idxm != idxn) {
2117 for (i = 0; i < n; i++) {
2118 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2119 }
2120 } else iidxn = iidxm;
2121 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2122 PetscCall(PetscFree2(bufr, bufc));
2123 }
2124 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2125 PetscFunctionReturn(PETSC_SUCCESS);
2126 }
2127
2128 /*@
2129 MatGetValues - Gets a block of local values from a matrix.
2130
2131 Not Collective; can only return values that are owned by the give process
2132
2133 Input Parameters:
2134 + mat - the matrix
2135 . v - a logically two-dimensional array for storing the values
2136 . m - the number of rows
2137 . idxm - the global indices of the rows
2138 . n - the number of columns
2139 - idxn - the global indices of the columns
2140
2141 Level: advanced
2142
2143 Notes:
2144 The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2145 The values, `v`, are then returned in a row-oriented format,
2146 analogous to that used by default in `MatSetValues()`.
2147
2148 `MatGetValues()` uses 0-based row and column numbers in
2149 Fortran as well as in C.
2150
2151 `MatGetValues()` requires that the matrix has been assembled
2152 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to
2153 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2154 without intermediate matrix assembly.
2155
2156 Negative row or column indices will be ignored and those locations in `v` will be
2157 left unchanged.
2158
2159 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2160 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2161 from `MatGetOwnershipRange`(mat,&rstart,&rend).
2162
2163 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2164 @*/
MatGetValues(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])2165 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2166 {
2167 PetscFunctionBegin;
2168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2169 PetscValidType(mat, 1);
2170 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2171 PetscAssertPointer(idxm, 3);
2172 PetscAssertPointer(idxn, 5);
2173 PetscAssertPointer(v, 6);
2174 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2175 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2176 MatCheckPreallocated(mat, 1);
2177
2178 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2179 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2180 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2181 PetscFunctionReturn(PETSC_SUCCESS);
2182 }
2183
2184 /*@
2185 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2186 defined previously by `MatSetLocalToGlobalMapping()`
2187
2188 Not Collective
2189
2190 Input Parameters:
2191 + mat - the matrix
2192 . nrow - number of rows
2193 . irow - the row local indices
2194 . ncol - number of columns
2195 - icol - the column local indices
2196
2197 Output Parameter:
2198 . y - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order.
2199 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
2200
2201 Level: advanced
2202
2203 Notes:
2204 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2205
2206 This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering,
2207 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2208 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2209 with `MatSetLocalToGlobalMapping()`.
2210
2211 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2212 `MatSetValuesLocal()`, `MatGetValues()`
2213 @*/
MatGetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],PetscScalar y[])2214 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2215 {
2216 PetscFunctionBeginHot;
2217 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2218 PetscValidType(mat, 1);
2219 MatCheckPreallocated(mat, 1);
2220 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2221 PetscAssertPointer(irow, 3);
2222 PetscAssertPointer(icol, 5);
2223 if (PetscDefined(USE_DEBUG)) {
2224 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2225 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2226 }
2227 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2228 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2229 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2230 else {
2231 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2232 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2233 irowm = buf;
2234 icolm = buf + nrow;
2235 } else {
2236 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2237 irowm = bufr;
2238 icolm = bufc;
2239 }
2240 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2241 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2242 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2243 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2244 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2245 PetscCall(PetscFree2(bufr, bufc));
2246 }
2247 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2248 PetscFunctionReturn(PETSC_SUCCESS);
2249 }
2250
2251 /*@
2252 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2253 the same size. Currently, this can only be called once and creates the given matrix.
2254
2255 Not Collective
2256
2257 Input Parameters:
2258 + mat - the matrix
2259 . nb - the number of blocks
2260 . bs - the number of rows (and columns) in each block
2261 . rows - a concatenation of the rows for each block
2262 - v - a concatenation of logically two-dimensional arrays of values
2263
2264 Level: advanced
2265
2266 Notes:
2267 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2268
2269 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2270
2271 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2272 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2273 @*/
MatSetValuesBatch(Mat mat,PetscInt nb,PetscInt bs,PetscInt rows[],const PetscScalar v[])2274 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2275 {
2276 PetscFunctionBegin;
2277 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2278 PetscValidType(mat, 1);
2279 PetscAssertPointer(rows, 4);
2280 PetscAssertPointer(v, 5);
2281 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2282
2283 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2284 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2285 else {
2286 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2287 }
2288 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2289 PetscFunctionReturn(PETSC_SUCCESS);
2290 }
2291
2292 /*@
2293 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2294 the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2295 using a local (per-processor) numbering.
2296
2297 Not Collective
2298
2299 Input Parameters:
2300 + x - the matrix
2301 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2302 - cmapping - column mapping
2303
2304 Level: intermediate
2305
2306 Note:
2307 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2308
2309 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2310 @*/
MatSetLocalToGlobalMapping(Mat x,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)2311 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2312 {
2313 PetscFunctionBegin;
2314 PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2315 PetscValidType(x, 1);
2316 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2317 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2318 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2319 else {
2320 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2321 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2322 }
2323 PetscFunctionReturn(PETSC_SUCCESS);
2324 }
2325
2326 /*@
2327 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2328
2329 Not Collective
2330
2331 Input Parameter:
2332 . A - the matrix
2333
2334 Output Parameters:
2335 + rmapping - row mapping
2336 - cmapping - column mapping
2337
2338 Level: advanced
2339
2340 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2341 @*/
MatGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping * rmapping,ISLocalToGlobalMapping * cmapping)2342 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2343 {
2344 PetscFunctionBegin;
2345 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2346 PetscValidType(A, 1);
2347 if (rmapping) {
2348 PetscAssertPointer(rmapping, 2);
2349 *rmapping = A->rmap->mapping;
2350 }
2351 if (cmapping) {
2352 PetscAssertPointer(cmapping, 3);
2353 *cmapping = A->cmap->mapping;
2354 }
2355 PetscFunctionReturn(PETSC_SUCCESS);
2356 }
2357
2358 /*@
2359 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2360
2361 Logically Collective
2362
2363 Input Parameters:
2364 + A - the matrix
2365 . rmap - row layout
2366 - cmap - column layout
2367
2368 Level: advanced
2369
2370 Note:
2371 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2372
2373 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2374 @*/
MatSetLayouts(Mat A,PetscLayout rmap,PetscLayout cmap)2375 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2376 {
2377 PetscFunctionBegin;
2378 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2379 PetscCall(PetscLayoutReference(rmap, &A->rmap));
2380 PetscCall(PetscLayoutReference(cmap, &A->cmap));
2381 PetscFunctionReturn(PETSC_SUCCESS);
2382 }
2383
2384 /*@
2385 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2386
2387 Not Collective
2388
2389 Input Parameter:
2390 . A - the matrix
2391
2392 Output Parameters:
2393 + rmap - row layout
2394 - cmap - column layout
2395
2396 Level: advanced
2397
2398 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2399 @*/
MatGetLayouts(Mat A,PetscLayout * rmap,PetscLayout * cmap)2400 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2401 {
2402 PetscFunctionBegin;
2403 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2404 PetscValidType(A, 1);
2405 if (rmap) {
2406 PetscAssertPointer(rmap, 2);
2407 *rmap = A->rmap;
2408 }
2409 if (cmap) {
2410 PetscAssertPointer(cmap, 3);
2411 *cmap = A->cmap;
2412 }
2413 PetscFunctionReturn(PETSC_SUCCESS);
2414 }
2415
2416 /*@
2417 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2418 using a local numbering of the rows and columns.
2419
2420 Not Collective
2421
2422 Input Parameters:
2423 + mat - the matrix
2424 . nrow - number of rows
2425 . irow - the row local indices
2426 . ncol - number of columns
2427 . icol - the column local indices
2428 . y - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order.
2429 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
2430 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2431
2432 Level: intermediate
2433
2434 Notes:
2435 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2436
2437 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2438 options cannot be mixed without intervening calls to the assembly
2439 routines.
2440
2441 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2442 MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2443
2444 Fortran Notes:
2445 If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2446 .vb
2447 call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2448 .ve
2449
2450 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2451
2452 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2453 `MatGetValuesLocal()`
2454 @*/
MatSetValuesLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)2455 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2456 {
2457 PetscFunctionBeginHot;
2458 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2459 PetscValidType(mat, 1);
2460 MatCheckPreallocated(mat, 1);
2461 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2462 PetscAssertPointer(irow, 3);
2463 PetscAssertPointer(icol, 5);
2464 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2465 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2466 if (PetscDefined(USE_DEBUG)) {
2467 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2468 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2469 }
2470
2471 if (mat->assembled) {
2472 mat->was_assembled = PETSC_TRUE;
2473 mat->assembled = PETSC_FALSE;
2474 }
2475 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2476 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2477 else {
2478 PetscInt buf[8192], *bufr = NULL, *bufc = NULL;
2479 const PetscInt *irowm, *icolm;
2480
2481 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2482 bufr = buf;
2483 bufc = buf + nrow;
2484 irowm = bufr;
2485 icolm = bufc;
2486 } else {
2487 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2488 irowm = bufr;
2489 icolm = bufc;
2490 }
2491 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2492 else irowm = irow;
2493 if (mat->cmap->mapping) {
2494 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2495 else icolm = irowm;
2496 } else icolm = icol;
2497 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2498 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2499 }
2500 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2501 PetscFunctionReturn(PETSC_SUCCESS);
2502 }
2503
2504 /*@
2505 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2506 using a local ordering of the nodes a block at a time.
2507
2508 Not Collective
2509
2510 Input Parameters:
2511 + mat - the matrix
2512 . nrow - number of rows
2513 . irow - the row local indices
2514 . ncol - number of columns
2515 . icol - the column local indices
2516 . y - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order.
2517 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
2518 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2519
2520 Level: intermediate
2521
2522 Notes:
2523 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2524 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2525
2526 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2527 options cannot be mixed without intervening calls to the assembly
2528 routines.
2529
2530 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2531 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2532
2533 Fortran Notes:
2534 If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2535 .vb
2536 call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2537 .ve
2538
2539 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2540
2541 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2542 `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2543 @*/
MatSetValuesBlockedLocal(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)2544 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2545 {
2546 PetscFunctionBeginHot;
2547 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2548 PetscValidType(mat, 1);
2549 MatCheckPreallocated(mat, 1);
2550 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2551 PetscAssertPointer(irow, 3);
2552 PetscAssertPointer(icol, 5);
2553 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2554 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2555 if (PetscDefined(USE_DEBUG)) {
2556 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2557 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2558 }
2559
2560 if (mat->assembled) {
2561 mat->was_assembled = PETSC_TRUE;
2562 mat->assembled = PETSC_FALSE;
2563 }
2564 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2565 PetscInt irbs, rbs;
2566 PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2567 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2568 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2569 }
2570 if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2571 PetscInt icbs, cbs;
2572 PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2573 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2574 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2575 }
2576 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2577 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2578 else {
2579 PetscInt buf[8192], *bufr = NULL, *bufc = NULL;
2580 const PetscInt *irowm, *icolm;
2581
2582 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2583 bufr = buf;
2584 bufc = buf + nrow;
2585 irowm = bufr;
2586 icolm = bufc;
2587 } else {
2588 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2589 irowm = bufr;
2590 icolm = bufc;
2591 }
2592 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2593 else irowm = irow;
2594 if (mat->cmap->mapping) {
2595 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2596 else icolm = irowm;
2597 } else icolm = icol;
2598 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2599 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2600 }
2601 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2602 PetscFunctionReturn(PETSC_SUCCESS);
2603 }
2604
2605 /*@
2606 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2607
2608 Collective
2609
2610 Input Parameters:
2611 + mat - the matrix
2612 - x - the vector to be multiplied
2613
2614 Output Parameter:
2615 . y - the result
2616
2617 Level: developer
2618
2619 Note:
2620 The vectors `x` and `y` cannot be the same. I.e., one cannot
2621 call `MatMultDiagonalBlock`(A,y,y).
2622
2623 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2624 @*/
MatMultDiagonalBlock(Mat mat,Vec x,Vec y)2625 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2626 {
2627 PetscFunctionBegin;
2628 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2629 PetscValidType(mat, 1);
2630 PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2631 PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2632
2633 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2634 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2635 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2636 MatCheckPreallocated(mat, 1);
2637
2638 PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2639 PetscCall(PetscObjectStateIncrease((PetscObject)y));
2640 PetscFunctionReturn(PETSC_SUCCESS);
2641 }
2642
2643 /*@
2644 MatMult - Computes the matrix-vector product, $y = Ax$.
2645
2646 Neighbor-wise Collective
2647
2648 Input Parameters:
2649 + mat - the matrix
2650 - x - the vector to be multiplied
2651
2652 Output Parameter:
2653 . y - the result
2654
2655 Level: beginner
2656
2657 Note:
2658 The vectors `x` and `y` cannot be the same. I.e., one cannot
2659 call `MatMult`(A,y,y).
2660
2661 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2662 @*/
MatMult(Mat mat,Vec x,Vec y)2663 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2664 {
2665 PetscFunctionBegin;
2666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2667 PetscValidType(mat, 1);
2668 PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2669 VecCheckAssembled(x);
2670 PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2671 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2672 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2673 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2674 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
2675 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
2676 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n);
2677 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n);
2678 PetscCall(VecSetErrorIfLocked(y, 3));
2679 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2680 MatCheckPreallocated(mat, 1);
2681
2682 PetscCall(VecLockReadPush(x));
2683 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2684 PetscUseTypeMethod(mat, mult, x, y);
2685 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2686 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2687 PetscCall(VecLockReadPop(x));
2688 PetscFunctionReturn(PETSC_SUCCESS);
2689 }
2690
2691 /*@
2692 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2693
2694 Neighbor-wise Collective
2695
2696 Input Parameters:
2697 + mat - the matrix
2698 - x - the vector to be multiplied
2699
2700 Output Parameter:
2701 . y - the result
2702
2703 Level: beginner
2704
2705 Notes:
2706 The vectors `x` and `y` cannot be the same. I.e., one cannot
2707 call `MatMultTranspose`(A,y,y).
2708
2709 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2710 use `MatMultHermitianTranspose()`
2711
2712 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2713 @*/
MatMultTranspose(Mat mat,Vec x,Vec y)2714 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2715 {
2716 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2717
2718 PetscFunctionBegin;
2719 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2720 PetscValidType(mat, 1);
2721 PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2722 VecCheckAssembled(x);
2723 PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2724
2725 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2726 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2727 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2728 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2729 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2730 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2731 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2732 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2733 MatCheckPreallocated(mat, 1);
2734
2735 if (!mat->ops->multtranspose) {
2736 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2737 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name);
2738 } else op = mat->ops->multtranspose;
2739 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2740 PetscCall(VecLockReadPush(x));
2741 PetscCall((*op)(mat, x, y));
2742 PetscCall(VecLockReadPop(x));
2743 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2744 PetscCall(PetscObjectStateIncrease((PetscObject)y));
2745 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2746 PetscFunctionReturn(PETSC_SUCCESS);
2747 }
2748
2749 /*@
2750 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2751
2752 Neighbor-wise Collective
2753
2754 Input Parameters:
2755 + mat - the matrix
2756 - x - the vector to be multiplied
2757
2758 Output Parameter:
2759 . y - the result
2760
2761 Level: beginner
2762
2763 Notes:
2764 The vectors `x` and `y` cannot be the same. I.e., one cannot
2765 call `MatMultHermitianTranspose`(A,y,y).
2766
2767 Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2768
2769 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2770
2771 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2772 @*/
MatMultHermitianTranspose(Mat mat,Vec x,Vec y)2773 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2774 {
2775 PetscFunctionBegin;
2776 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2777 PetscValidType(mat, 1);
2778 PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2779 PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2780
2781 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2782 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2783 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2784 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2785 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2786 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2787 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2788 MatCheckPreallocated(mat, 1);
2789
2790 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2791 #if defined(PETSC_USE_COMPLEX)
2792 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2793 PetscCall(VecLockReadPush(x));
2794 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2795 else PetscUseTypeMethod(mat, mult, x, y);
2796 PetscCall(VecLockReadPop(x));
2797 } else {
2798 Vec w;
2799 PetscCall(VecDuplicate(x, &w));
2800 PetscCall(VecCopy(x, w));
2801 PetscCall(VecConjugate(w));
2802 PetscCall(MatMultTranspose(mat, w, y));
2803 PetscCall(VecDestroy(&w));
2804 PetscCall(VecConjugate(y));
2805 }
2806 PetscCall(PetscObjectStateIncrease((PetscObject)y));
2807 #else
2808 PetscCall(MatMultTranspose(mat, x, y));
2809 #endif
2810 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2811 PetscFunctionReturn(PETSC_SUCCESS);
2812 }
2813
2814 /*@
2815 MatMultAdd - Computes $v3 = v2 + A * v1$.
2816
2817 Neighbor-wise Collective
2818
2819 Input Parameters:
2820 + mat - the matrix
2821 . v1 - the vector to be multiplied by `mat`
2822 - v2 - the vector to be added to the result
2823
2824 Output Parameter:
2825 . v3 - the result
2826
2827 Level: beginner
2828
2829 Note:
2830 The vectors `v1` and `v3` cannot be the same. I.e., one cannot
2831 call `MatMultAdd`(A,v1,v2,v1).
2832
2833 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2834 @*/
MatMultAdd(Mat mat,Vec v1,Vec v2,Vec v3)2835 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2836 {
2837 PetscFunctionBegin;
2838 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2839 PetscValidType(mat, 1);
2840 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2841 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2842 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2843
2844 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2845 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2846 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N);
2847 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2848 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2849 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n);
2850 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n);
2851 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2852 MatCheckPreallocated(mat, 1);
2853
2854 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2855 PetscCall(VecLockReadPush(v1));
2856 PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2857 PetscCall(VecLockReadPop(v1));
2858 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2859 PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2860 PetscFunctionReturn(PETSC_SUCCESS);
2861 }
2862
2863 /*@
2864 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2865
2866 Neighbor-wise Collective
2867
2868 Input Parameters:
2869 + mat - the matrix
2870 . v1 - the vector to be multiplied by the transpose of the matrix
2871 - v2 - the vector to be added to the result
2872
2873 Output Parameter:
2874 . v3 - the result
2875
2876 Level: beginner
2877
2878 Note:
2879 The vectors `v1` and `v3` cannot be the same. I.e., one cannot
2880 call `MatMultTransposeAdd`(A,v1,v2,v1).
2881
2882 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2883 @*/
MatMultTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)2884 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2885 {
2886 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2887
2888 PetscFunctionBegin;
2889 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2890 PetscValidType(mat, 1);
2891 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2892 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2893 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2894
2895 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2896 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2897 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2898 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2899 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2900 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2901 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2902 MatCheckPreallocated(mat, 1);
2903
2904 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2905 PetscCall(VecLockReadPush(v1));
2906 PetscCall((*op)(mat, v1, v2, v3));
2907 PetscCall(VecLockReadPop(v1));
2908 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2909 PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2910 PetscFunctionReturn(PETSC_SUCCESS);
2911 }
2912
2913 /*@
2914 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2915
2916 Neighbor-wise Collective
2917
2918 Input Parameters:
2919 + mat - the matrix
2920 . v1 - the vector to be multiplied by the Hermitian transpose
2921 - v2 - the vector to be added to the result
2922
2923 Output Parameter:
2924 . v3 - the result
2925
2926 Level: beginner
2927
2928 Note:
2929 The vectors `v1` and `v3` cannot be the same. I.e., one cannot
2930 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2931
2932 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2933 @*/
MatMultHermitianTransposeAdd(Mat mat,Vec v1,Vec v2,Vec v3)2934 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2935 {
2936 PetscFunctionBegin;
2937 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2938 PetscValidType(mat, 1);
2939 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2940 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2941 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2942
2943 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2944 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2945 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2946 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2947 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2948 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2949 MatCheckPreallocated(mat, 1);
2950
2951 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2952 PetscCall(VecLockReadPush(v1));
2953 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2954 else {
2955 Vec w, z;
2956 PetscCall(VecDuplicate(v1, &w));
2957 PetscCall(VecCopy(v1, w));
2958 PetscCall(VecConjugate(w));
2959 PetscCall(VecDuplicate(v3, &z));
2960 PetscCall(MatMultTranspose(mat, w, z));
2961 PetscCall(VecDestroy(&w));
2962 PetscCall(VecConjugate(z));
2963 if (v2 != v3) {
2964 PetscCall(VecWAXPY(v3, 1.0, v2, z));
2965 } else {
2966 PetscCall(VecAXPY(v3, 1.0, z));
2967 }
2968 PetscCall(VecDestroy(&z));
2969 }
2970 PetscCall(VecLockReadPop(v1));
2971 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2972 PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2973 PetscFunctionReturn(PETSC_SUCCESS);
2974 }
2975
2976 /*@
2977 MatGetFactorType - gets the type of factorization a matrix is
2978
2979 Not Collective
2980
2981 Input Parameter:
2982 . mat - the matrix
2983
2984 Output Parameter:
2985 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2986
2987 Level: intermediate
2988
2989 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2990 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2991 @*/
MatGetFactorType(Mat mat,MatFactorType * t)2992 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2993 {
2994 PetscFunctionBegin;
2995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2996 PetscValidType(mat, 1);
2997 PetscAssertPointer(t, 2);
2998 *t = mat->factortype;
2999 PetscFunctionReturn(PETSC_SUCCESS);
3000 }
3001
3002 /*@
3003 MatSetFactorType - sets the type of factorization a matrix is
3004
3005 Logically Collective
3006
3007 Input Parameters:
3008 + mat - the matrix
3009 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3010
3011 Level: intermediate
3012
3013 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3014 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3015 @*/
MatSetFactorType(Mat mat,MatFactorType t)3016 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
3017 {
3018 PetscFunctionBegin;
3019 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3020 PetscValidType(mat, 1);
3021 mat->factortype = t;
3022 PetscFunctionReturn(PETSC_SUCCESS);
3023 }
3024
3025 /*@
3026 MatGetInfo - Returns information about matrix storage (number of
3027 nonzeros, memory, etc.).
3028
3029 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3030
3031 Input Parameters:
3032 + mat - the matrix
3033 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors)
3034
3035 Output Parameter:
3036 . info - matrix information context
3037
3038 Options Database Key:
3039 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3040
3041 Level: intermediate
3042
3043 Notes:
3044 The `MatInfo` context contains a variety of matrix data, including
3045 number of nonzeros allocated and used, number of mallocs during
3046 matrix assembly, etc. Additional information for factored matrices
3047 is provided (such as the fill ratio, number of mallocs during
3048 factorization, etc.).
3049
3050 Example:
3051 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3052 data within the `MatInfo` context. For example,
3053 .vb
3054 MatInfo info;
3055 Mat A;
3056 double mal, nz_a, nz_u;
3057
3058 MatGetInfo(A, MAT_LOCAL, &info);
3059 mal = info.mallocs;
3060 nz_a = info.nz_allocated;
3061 .ve
3062
3063 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3064 @*/
MatGetInfo(Mat mat,MatInfoType flag,MatInfo * info)3065 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3066 {
3067 PetscFunctionBegin;
3068 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3069 PetscValidType(mat, 1);
3070 PetscAssertPointer(info, 3);
3071 MatCheckPreallocated(mat, 1);
3072 PetscUseTypeMethod(mat, getinfo, flag, info);
3073 PetscFunctionReturn(PETSC_SUCCESS);
3074 }
3075
3076 /*
3077 This is used by external packages where it is not easy to get the info from the actual
3078 matrix factorization.
3079 */
MatGetInfo_External(Mat A,MatInfoType flag,MatInfo * info)3080 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3081 {
3082 PetscFunctionBegin;
3083 PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3084 PetscFunctionReturn(PETSC_SUCCESS);
3085 }
3086
3087 /*@
3088 MatLUFactor - Performs in-place LU factorization of matrix.
3089
3090 Collective
3091
3092 Input Parameters:
3093 + mat - the matrix
3094 . row - row permutation
3095 . col - column permutation
3096 - info - options for factorization, includes
3097 .vb
3098 fill - expected fill as ratio of original fill.
3099 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3100 Run with the option -info to determine an optimal value to use
3101 .ve
3102
3103 Level: developer
3104
3105 Notes:
3106 Most users should employ the `KSP` interface for linear solvers
3107 instead of working directly with matrix algebra routines such as this.
3108 See, e.g., `KSPCreate()`.
3109
3110 This changes the state of the matrix to a factored matrix; it cannot be used
3111 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3112
3113 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3114 when not using `KSP`.
3115
3116 Fortran Note:
3117 A valid (non-null) `info` argument must be provided
3118
3119 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3120 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3121 @*/
MatLUFactor(Mat mat,IS row,IS col,const MatFactorInfo * info)3122 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3123 {
3124 MatFactorInfo tinfo;
3125
3126 PetscFunctionBegin;
3127 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3128 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3129 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3130 if (info) PetscAssertPointer(info, 4);
3131 PetscValidType(mat, 1);
3132 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3133 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3134 MatCheckPreallocated(mat, 1);
3135 if (!info) {
3136 PetscCall(MatFactorInfoInitialize(&tinfo));
3137 info = &tinfo;
3138 }
3139
3140 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3141 PetscUseTypeMethod(mat, lufactor, row, col, info);
3142 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3143 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3144 PetscFunctionReturn(PETSC_SUCCESS);
3145 }
3146
3147 /*@
3148 MatILUFactor - Performs in-place ILU factorization of matrix.
3149
3150 Collective
3151
3152 Input Parameters:
3153 + mat - the matrix
3154 . row - row permutation
3155 . col - column permutation
3156 - info - structure containing
3157 .vb
3158 levels - number of levels of fill.
3159 expected fill - as ratio of original fill.
3160 1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3161 missing diagonal entries)
3162 .ve
3163
3164 Level: developer
3165
3166 Notes:
3167 Most users should employ the `KSP` interface for linear solvers
3168 instead of working directly with matrix algebra routines such as this.
3169 See, e.g., `KSPCreate()`.
3170
3171 Probably really in-place only when level of fill is zero, otherwise allocates
3172 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3173 when not using `KSP`.
3174
3175 Fortran Note:
3176 A valid (non-null) `info` argument must be provided
3177
3178 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3179 @*/
MatILUFactor(Mat mat,IS row,IS col,const MatFactorInfo * info)3180 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3181 {
3182 PetscFunctionBegin;
3183 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3184 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3185 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3186 PetscAssertPointer(info, 4);
3187 PetscValidType(mat, 1);
3188 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3189 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3190 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3191 MatCheckPreallocated(mat, 1);
3192
3193 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3194 PetscUseTypeMethod(mat, ilufactor, row, col, info);
3195 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3196 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3197 PetscFunctionReturn(PETSC_SUCCESS);
3198 }
3199
3200 /*@
3201 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3202 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3203
3204 Collective
3205
3206 Input Parameters:
3207 + fact - the factor matrix obtained with `MatGetFactor()`
3208 . mat - the matrix
3209 . row - the row permutation
3210 . col - the column permutation
3211 - info - options for factorization, includes
3212 .vb
3213 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3214 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3215 .ve
3216
3217 Level: developer
3218
3219 Notes:
3220 See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3221
3222 Most users should employ the simplified `KSP` interface for linear solvers
3223 instead of working directly with matrix algebra routines such as this.
3224 See, e.g., `KSPCreate()`.
3225
3226 Fortran Note:
3227 A valid (non-null) `info` argument must be provided
3228
3229 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3230 @*/
MatLUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo * info)3231 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3232 {
3233 MatFactorInfo tinfo;
3234
3235 PetscFunctionBegin;
3236 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3238 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3239 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3240 if (info) PetscAssertPointer(info, 5);
3241 PetscValidType(fact, 1);
3242 PetscValidType(mat, 2);
3243 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3244 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3245 MatCheckPreallocated(mat, 2);
3246 if (!info) {
3247 PetscCall(MatFactorInfoInitialize(&tinfo));
3248 info = &tinfo;
3249 }
3250
3251 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3252 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3253 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3254 PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3255 PetscFunctionReturn(PETSC_SUCCESS);
3256 }
3257
3258 /*@
3259 MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3260 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3261
3262 Collective
3263
3264 Input Parameters:
3265 + fact - the factor matrix obtained with `MatGetFactor()`
3266 . mat - the matrix
3267 - info - options for factorization
3268
3269 Level: developer
3270
3271 Notes:
3272 See `MatLUFactor()` for in-place factorization. See
3273 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3274
3275 Most users should employ the `KSP` interface for linear solvers
3276 instead of working directly with matrix algebra routines such as this.
3277 See, e.g., `KSPCreate()`.
3278
3279 Fortran Note:
3280 A valid (non-null) `info` argument must be provided
3281
3282 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3283 @*/
MatLUFactorNumeric(Mat fact,Mat mat,const MatFactorInfo * info)3284 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3285 {
3286 MatFactorInfo tinfo;
3287
3288 PetscFunctionBegin;
3289 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3291 PetscValidType(fact, 1);
3292 PetscValidType(mat, 2);
3293 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3294 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3295 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3296
3297 MatCheckPreallocated(mat, 2);
3298 if (!info) {
3299 PetscCall(MatFactorInfoInitialize(&tinfo));
3300 info = &tinfo;
3301 }
3302
3303 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3304 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3305 PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3306 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3307 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3308 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3309 PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3310 PetscFunctionReturn(PETSC_SUCCESS);
3311 }
3312
3313 /*@
3314 MatCholeskyFactor - Performs in-place Cholesky factorization of a
3315 symmetric matrix.
3316
3317 Collective
3318
3319 Input Parameters:
3320 + mat - the matrix
3321 . perm - row and column permutations
3322 - info - expected fill as ratio of original fill
3323
3324 Level: developer
3325
3326 Notes:
3327 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`,
3328 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3329
3330 Most users should employ the `KSP` interface for linear solvers
3331 instead of working directly with matrix algebra routines such as this.
3332 See, e.g., `KSPCreate()`.
3333
3334 Fortran Note:
3335 A valid (non-null) `info` argument must be provided
3336
3337 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3338 `MatGetOrdering()`
3339 @*/
MatCholeskyFactor(Mat mat,IS perm,const MatFactorInfo * info)3340 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3341 {
3342 MatFactorInfo tinfo;
3343
3344 PetscFunctionBegin;
3345 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3346 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3347 if (info) PetscAssertPointer(info, 3);
3348 PetscValidType(mat, 1);
3349 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3350 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3351 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3352 MatCheckPreallocated(mat, 1);
3353 if (!info) {
3354 PetscCall(MatFactorInfoInitialize(&tinfo));
3355 info = &tinfo;
3356 }
3357
3358 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3359 PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3360 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3361 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3362 PetscFunctionReturn(PETSC_SUCCESS);
3363 }
3364
3365 /*@
3366 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3367 of a symmetric matrix.
3368
3369 Collective
3370
3371 Input Parameters:
3372 + fact - the factor matrix obtained with `MatGetFactor()`
3373 . mat - the matrix
3374 . perm - row and column permutations
3375 - info - options for factorization, includes
3376 .vb
3377 fill - expected fill as ratio of original fill.
3378 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3379 Run with the option -info to determine an optimal value to use
3380 .ve
3381
3382 Level: developer
3383
3384 Notes:
3385 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also
3386 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3387
3388 Most users should employ the `KSP` interface for linear solvers
3389 instead of working directly with matrix algebra routines such as this.
3390 See, e.g., `KSPCreate()`.
3391
3392 Fortran Note:
3393 A valid (non-null) `info` argument must be provided
3394
3395 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3396 `MatGetOrdering()`
3397 @*/
MatCholeskyFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo * info)3398 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3399 {
3400 MatFactorInfo tinfo;
3401
3402 PetscFunctionBegin;
3403 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3404 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3405 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3406 if (info) PetscAssertPointer(info, 4);
3407 PetscValidType(fact, 1);
3408 PetscValidType(mat, 2);
3409 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3410 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3411 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3412 MatCheckPreallocated(mat, 2);
3413 if (!info) {
3414 PetscCall(MatFactorInfoInitialize(&tinfo));
3415 info = &tinfo;
3416 }
3417
3418 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3419 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3420 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3421 PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3422 PetscFunctionReturn(PETSC_SUCCESS);
3423 }
3424
3425 /*@
3426 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3427 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3428 `MatCholeskyFactorSymbolic()`.
3429
3430 Collective
3431
3432 Input Parameters:
3433 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3434 . mat - the initial matrix that is to be factored
3435 - info - options for factorization
3436
3437 Level: developer
3438
3439 Note:
3440 Most users should employ the `KSP` interface for linear solvers
3441 instead of working directly with matrix algebra routines such as this.
3442 See, e.g., `KSPCreate()`.
3443
3444 Fortran Note:
3445 A valid (non-null) `info` argument must be provided
3446
3447 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3448 @*/
MatCholeskyFactorNumeric(Mat fact,Mat mat,const MatFactorInfo * info)3449 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3450 {
3451 MatFactorInfo tinfo;
3452
3453 PetscFunctionBegin;
3454 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3455 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3456 PetscValidType(fact, 1);
3457 PetscValidType(mat, 2);
3458 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3459 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3460 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3461 MatCheckPreallocated(mat, 2);
3462 if (!info) {
3463 PetscCall(MatFactorInfoInitialize(&tinfo));
3464 info = &tinfo;
3465 }
3466
3467 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3468 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3469 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3470 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3471 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3472 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3473 PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3474 PetscFunctionReturn(PETSC_SUCCESS);
3475 }
3476
3477 /*@
3478 MatQRFactor - Performs in-place QR factorization of matrix.
3479
3480 Collective
3481
3482 Input Parameters:
3483 + mat - the matrix
3484 . col - column permutation
3485 - info - options for factorization, includes
3486 .vb
3487 fill - expected fill as ratio of original fill.
3488 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3489 Run with the option -info to determine an optimal value to use
3490 .ve
3491
3492 Level: developer
3493
3494 Notes:
3495 Most users should employ the `KSP` interface for linear solvers
3496 instead of working directly with matrix algebra routines such as this.
3497 See, e.g., `KSPCreate()`.
3498
3499 This changes the state of the matrix to a factored matrix; it cannot be used
3500 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3501
3502 Fortran Note:
3503 A valid (non-null) `info` argument must be provided
3504
3505 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3506 `MatSetUnfactored()`
3507 @*/
MatQRFactor(Mat mat,IS col,const MatFactorInfo * info)3508 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3509 {
3510 PetscFunctionBegin;
3511 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3512 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3513 if (info) PetscAssertPointer(info, 3);
3514 PetscValidType(mat, 1);
3515 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3516 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3517 MatCheckPreallocated(mat, 1);
3518 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3519 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3520 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3521 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3522 PetscFunctionReturn(PETSC_SUCCESS);
3523 }
3524
3525 /*@
3526 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3527 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3528
3529 Collective
3530
3531 Input Parameters:
3532 + fact - the factor matrix obtained with `MatGetFactor()`
3533 . mat - the matrix
3534 . col - column permutation
3535 - info - options for factorization, includes
3536 .vb
3537 fill - expected fill as ratio of original fill.
3538 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3539 Run with the option -info to determine an optimal value to use
3540 .ve
3541
3542 Level: developer
3543
3544 Note:
3545 Most users should employ the `KSP` interface for linear solvers
3546 instead of working directly with matrix algebra routines such as this.
3547 See, e.g., `KSPCreate()`.
3548
3549 Fortran Note:
3550 A valid (non-null) `info` argument must be provided
3551
3552 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3553 @*/
MatQRFactorSymbolic(Mat fact,Mat mat,IS col,const MatFactorInfo * info)3554 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3555 {
3556 MatFactorInfo tinfo;
3557
3558 PetscFunctionBegin;
3559 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3561 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3562 if (info) PetscAssertPointer(info, 4);
3563 PetscValidType(fact, 1);
3564 PetscValidType(mat, 2);
3565 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3566 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3567 MatCheckPreallocated(mat, 2);
3568 if (!info) {
3569 PetscCall(MatFactorInfoInitialize(&tinfo));
3570 info = &tinfo;
3571 }
3572
3573 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3574 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3575 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3576 PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3577 PetscFunctionReturn(PETSC_SUCCESS);
3578 }
3579
3580 /*@
3581 MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3582 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3583
3584 Collective
3585
3586 Input Parameters:
3587 + fact - the factor matrix obtained with `MatGetFactor()`
3588 . mat - the matrix
3589 - info - options for factorization
3590
3591 Level: developer
3592
3593 Notes:
3594 See `MatQRFactor()` for in-place factorization.
3595
3596 Most users should employ the `KSP` interface for linear solvers
3597 instead of working directly with matrix algebra routines such as this.
3598 See, e.g., `KSPCreate()`.
3599
3600 Fortran Note:
3601 A valid (non-null) `info` argument must be provided
3602
3603 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3604 @*/
MatQRFactorNumeric(Mat fact,Mat mat,const MatFactorInfo * info)3605 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3606 {
3607 MatFactorInfo tinfo;
3608
3609 PetscFunctionBegin;
3610 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3611 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3612 PetscValidType(fact, 1);
3613 PetscValidType(mat, 2);
3614 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3615 PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3616 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3617
3618 MatCheckPreallocated(mat, 2);
3619 if (!info) {
3620 PetscCall(MatFactorInfoInitialize(&tinfo));
3621 info = &tinfo;
3622 }
3623
3624 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3625 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3626 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3627 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3628 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3629 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3630 PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3631 PetscFunctionReturn(PETSC_SUCCESS);
3632 }
3633
3634 /*@
3635 MatSolve - Solves $A x = b$, given a factored matrix.
3636
3637 Neighbor-wise Collective
3638
3639 Input Parameters:
3640 + mat - the factored matrix
3641 - b - the right-hand-side vector
3642
3643 Output Parameter:
3644 . x - the result vector
3645
3646 Level: developer
3647
3648 Notes:
3649 The vectors `b` and `x` cannot be the same. I.e., one cannot
3650 call `MatSolve`(A,x,x).
3651
3652 Most users should employ the `KSP` interface for linear solvers
3653 instead of working directly with matrix algebra routines such as this.
3654 See, e.g., `KSPCreate()`.
3655
3656 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3657 @*/
MatSolve(Mat mat,Vec b,Vec x)3658 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3659 {
3660 PetscFunctionBegin;
3661 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3662 PetscValidType(mat, 1);
3663 PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3664 PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3665 PetscCheckSameComm(mat, 1, b, 2);
3666 PetscCheckSameComm(mat, 1, x, 3);
3667 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3668 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3669 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3670 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3671 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3672 MatCheckPreallocated(mat, 1);
3673
3674 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3675 PetscCall(VecFlag(x, mat->factorerrortype));
3676 if (mat->factorerrortype) PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3677 else PetscUseTypeMethod(mat, solve, b, x);
3678 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3679 PetscCall(PetscObjectStateIncrease((PetscObject)x));
3680 PetscFunctionReturn(PETSC_SUCCESS);
3681 }
3682
MatMatSolve_Basic(Mat A,Mat B,Mat X,PetscBool trans)3683 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3684 {
3685 Vec b, x;
3686 PetscInt N, i;
3687 PetscErrorCode (*f)(Mat, Vec, Vec);
3688 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3689
3690 PetscFunctionBegin;
3691 if (A->factorerrortype) {
3692 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3693 PetscCall(MatSetInf(X));
3694 PetscFunctionReturn(PETSC_SUCCESS);
3695 }
3696 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3697 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3698 PetscCall(MatBoundToCPU(A, &Abound));
3699 if (!Abound) {
3700 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3701 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3702 }
3703 #if PetscDefined(HAVE_CUDA)
3704 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3705 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3706 #elif PetscDefined(HAVE_HIP)
3707 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3708 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3709 #endif
3710 PetscCall(MatGetSize(B, NULL, &N));
3711 for (i = 0; i < N; i++) {
3712 PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3713 PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3714 PetscCall((*f)(A, b, x));
3715 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3716 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3717 }
3718 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3719 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3720 PetscFunctionReturn(PETSC_SUCCESS);
3721 }
3722
3723 /*@
3724 MatMatSolve - Solves $A X = B$, given a factored matrix.
3725
3726 Neighbor-wise Collective
3727
3728 Input Parameters:
3729 + A - the factored matrix
3730 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3731
3732 Output Parameter:
3733 . X - the result matrix (dense matrix)
3734
3735 Level: developer
3736
3737 Note:
3738 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3739 otherwise, `B` and `X` cannot be the same.
3740
3741 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3742 @*/
MatMatSolve(Mat A,Mat B,Mat X)3743 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3744 {
3745 PetscFunctionBegin;
3746 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3747 PetscValidType(A, 1);
3748 PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3749 PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3750 PetscCheckSameComm(A, 1, B, 2);
3751 PetscCheckSameComm(A, 1, X, 3);
3752 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3753 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3754 PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3755 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3756 MatCheckPreallocated(A, 1);
3757
3758 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3759 if (!A->ops->matsolve) {
3760 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3761 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3762 } else PetscUseTypeMethod(A, matsolve, B, X);
3763 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3764 PetscCall(PetscObjectStateIncrease((PetscObject)X));
3765 PetscFunctionReturn(PETSC_SUCCESS);
3766 }
3767
3768 /*@
3769 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3770
3771 Neighbor-wise Collective
3772
3773 Input Parameters:
3774 + A - the factored matrix
3775 - B - the right-hand-side matrix (`MATDENSE` matrix)
3776
3777 Output Parameter:
3778 . X - the result matrix (dense matrix)
3779
3780 Level: developer
3781
3782 Note:
3783 The matrices `B` and `X` cannot be the same. I.e., one cannot
3784 call `MatMatSolveTranspose`(A,X,X).
3785
3786 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3787 @*/
MatMatSolveTranspose(Mat A,Mat B,Mat X)3788 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3789 {
3790 PetscFunctionBegin;
3791 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3792 PetscValidType(A, 1);
3793 PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3794 PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3795 PetscCheckSameComm(A, 1, B, 2);
3796 PetscCheckSameComm(A, 1, X, 3);
3797 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3798 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3799 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3800 PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n);
3801 PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3802 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3803 MatCheckPreallocated(A, 1);
3804
3805 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3806 if (!A->ops->matsolvetranspose) {
3807 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3808 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3809 } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3810 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3811 PetscCall(PetscObjectStateIncrease((PetscObject)X));
3812 PetscFunctionReturn(PETSC_SUCCESS);
3813 }
3814
3815 /*@
3816 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3817
3818 Neighbor-wise Collective
3819
3820 Input Parameters:
3821 + A - the factored matrix
3822 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3823
3824 Output Parameter:
3825 . X - the result matrix (dense matrix)
3826
3827 Level: developer
3828
3829 Note:
3830 For MUMPS, it only supports centralized sparse compressed column format on the host processor for right-hand side matrix. User must create `Bt` in sparse compressed row
3831 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3832
3833 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3834 @*/
MatMatTransposeSolve(Mat A,Mat Bt,Mat X)3835 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3836 {
3837 PetscFunctionBegin;
3838 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3839 PetscValidType(A, 1);
3840 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3841 PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3842 PetscCheckSameComm(A, 1, Bt, 2);
3843 PetscCheckSameComm(A, 1, X, 3);
3844
3845 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3846 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3847 PetscCheck(A->rmap->N == Bt->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, Bt->cmap->N);
3848 PetscCheck(X->cmap->N >= Bt->rmap->N, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as row number of the rhs matrix");
3849 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3850 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3851 MatCheckPreallocated(A, 1);
3852
3853 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3854 PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3855 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3856 PetscCall(PetscObjectStateIncrease((PetscObject)X));
3857 PetscFunctionReturn(PETSC_SUCCESS);
3858 }
3859
3860 /*@
3861 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3862 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3863
3864 Neighbor-wise Collective
3865
3866 Input Parameters:
3867 + mat - the factored matrix
3868 - b - the right-hand-side vector
3869
3870 Output Parameter:
3871 . x - the result vector
3872
3873 Level: developer
3874
3875 Notes:
3876 `MatSolve()` should be used for most applications, as it performs
3877 a forward solve followed by a backward solve.
3878
3879 The vectors `b` and `x` cannot be the same, i.e., one cannot
3880 call `MatForwardSolve`(A,x,x).
3881
3882 For matrix in `MATSEQBAIJ` format with block size larger than 1,
3883 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3884 `MatForwardSolve()` solves $U^T*D y = b$, and
3885 `MatBackwardSolve()` solves $U x = y$.
3886 Thus they do not provide a symmetric preconditioner.
3887
3888 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3889 @*/
MatForwardSolve(Mat mat,Vec b,Vec x)3890 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3891 {
3892 PetscFunctionBegin;
3893 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3894 PetscValidType(mat, 1);
3895 PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3896 PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3897 PetscCheckSameComm(mat, 1, b, 2);
3898 PetscCheckSameComm(mat, 1, x, 3);
3899 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3900 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3901 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3902 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3903 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3904 MatCheckPreallocated(mat, 1);
3905
3906 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3907 PetscUseTypeMethod(mat, forwardsolve, b, x);
3908 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3909 PetscCall(PetscObjectStateIncrease((PetscObject)x));
3910 PetscFunctionReturn(PETSC_SUCCESS);
3911 }
3912
3913 /*@
3914 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3915 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3916
3917 Neighbor-wise Collective
3918
3919 Input Parameters:
3920 + mat - the factored matrix
3921 - b - the right-hand-side vector
3922
3923 Output Parameter:
3924 . x - the result vector
3925
3926 Level: developer
3927
3928 Notes:
3929 `MatSolve()` should be used for most applications, as it performs
3930 a forward solve followed by a backward solve.
3931
3932 The vectors `b` and `x` cannot be the same. I.e., one cannot
3933 call `MatBackwardSolve`(A,x,x).
3934
3935 For matrix in `MATSEQBAIJ` format with block size larger than 1,
3936 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3937 `MatForwardSolve()` solves $U^T*D y = b$, and
3938 `MatBackwardSolve()` solves $U x = y$.
3939 Thus they do not provide a symmetric preconditioner.
3940
3941 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3942 @*/
MatBackwardSolve(Mat mat,Vec b,Vec x)3943 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3944 {
3945 PetscFunctionBegin;
3946 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3947 PetscValidType(mat, 1);
3948 PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3949 PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3950 PetscCheckSameComm(mat, 1, b, 2);
3951 PetscCheckSameComm(mat, 1, x, 3);
3952 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3953 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3954 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3955 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3956 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3957 MatCheckPreallocated(mat, 1);
3958
3959 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3960 PetscUseTypeMethod(mat, backwardsolve, b, x);
3961 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3962 PetscCall(PetscObjectStateIncrease((PetscObject)x));
3963 PetscFunctionReturn(PETSC_SUCCESS);
3964 }
3965
3966 /*@
3967 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3968
3969 Neighbor-wise Collective
3970
3971 Input Parameters:
3972 + mat - the factored matrix
3973 . b - the right-hand-side vector
3974 - y - the vector to be added to
3975
3976 Output Parameter:
3977 . x - the result vector
3978
3979 Level: developer
3980
3981 Note:
3982 The vectors `b` and `x` cannot be the same. I.e., one cannot
3983 call `MatSolveAdd`(A,x,y,x).
3984
3985 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3986 @*/
MatSolveAdd(Mat mat,Vec b,Vec y,Vec x)3987 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3988 {
3989 PetscScalar one = 1.0;
3990 Vec tmp;
3991
3992 PetscFunctionBegin;
3993 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3994 PetscValidType(mat, 1);
3995 PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3996 PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3997 PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3998 PetscCheckSameComm(mat, 1, b, 2);
3999 PetscCheckSameComm(mat, 1, y, 3);
4000 PetscCheckSameComm(mat, 1, x, 4);
4001 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4002 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
4003 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
4004 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
4005 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
4006 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n);
4007 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4008 MatCheckPreallocated(mat, 1);
4009
4010 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4011 PetscCall(VecFlag(x, mat->factorerrortype));
4012 if (mat->factorerrortype) {
4013 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4014 } else if (mat->ops->solveadd) {
4015 PetscUseTypeMethod(mat, solveadd, b, y, x);
4016 } else {
4017 /* do the solve then the add manually */
4018 if (x != y) {
4019 PetscCall(MatSolve(mat, b, x));
4020 PetscCall(VecAXPY(x, one, y));
4021 } else {
4022 PetscCall(VecDuplicate(x, &tmp));
4023 PetscCall(VecCopy(x, tmp));
4024 PetscCall(MatSolve(mat, b, x));
4025 PetscCall(VecAXPY(x, one, tmp));
4026 PetscCall(VecDestroy(&tmp));
4027 }
4028 }
4029 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4030 PetscCall(PetscObjectStateIncrease((PetscObject)x));
4031 PetscFunctionReturn(PETSC_SUCCESS);
4032 }
4033
4034 /*@
4035 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4036
4037 Neighbor-wise Collective
4038
4039 Input Parameters:
4040 + mat - the factored matrix
4041 - b - the right-hand-side vector
4042
4043 Output Parameter:
4044 . x - the result vector
4045
4046 Level: developer
4047
4048 Notes:
4049 The vectors `b` and `x` cannot be the same. I.e., one cannot
4050 call `MatSolveTranspose`(A,x,x).
4051
4052 Most users should employ the `KSP` interface for linear solvers
4053 instead of working directly with matrix algebra routines such as this.
4054 See, e.g., `KSPCreate()`.
4055
4056 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4057 @*/
MatSolveTranspose(Mat mat,Vec b,Vec x)4058 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4059 {
4060 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4061
4062 PetscFunctionBegin;
4063 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4064 PetscValidType(mat, 1);
4065 PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4066 PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4067 PetscCheckSameComm(mat, 1, b, 2);
4068 PetscCheckSameComm(mat, 1, x, 3);
4069 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4070 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
4071 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N);
4072 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4073 MatCheckPreallocated(mat, 1);
4074 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4075 PetscCall(VecFlag(x, mat->factorerrortype));
4076 if (mat->factorerrortype) {
4077 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4078 } else {
4079 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4080 PetscCall((*f)(mat, b, x));
4081 }
4082 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4083 PetscCall(PetscObjectStateIncrease((PetscObject)x));
4084 PetscFunctionReturn(PETSC_SUCCESS);
4085 }
4086
4087 /*@
4088 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4089 factored matrix.
4090
4091 Neighbor-wise Collective
4092
4093 Input Parameters:
4094 + mat - the factored matrix
4095 . b - the right-hand-side vector
4096 - y - the vector to be added to
4097
4098 Output Parameter:
4099 . x - the result vector
4100
4101 Level: developer
4102
4103 Note:
4104 The vectors `b` and `x` cannot be the same. I.e., one cannot
4105 call `MatSolveTransposeAdd`(A,x,y,x).
4106
4107 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4108 @*/
MatSolveTransposeAdd(Mat mat,Vec b,Vec y,Vec x)4109 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4110 {
4111 PetscScalar one = 1.0;
4112 Vec tmp;
4113 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4114
4115 PetscFunctionBegin;
4116 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4117 PetscValidType(mat, 1);
4118 PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4119 PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4120 PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4121 PetscCheckSameComm(mat, 1, b, 2);
4122 PetscCheckSameComm(mat, 1, y, 3);
4123 PetscCheckSameComm(mat, 1, x, 4);
4124 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4125 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
4126 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N);
4127 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
4128 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n);
4129 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4130 MatCheckPreallocated(mat, 1);
4131
4132 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4133 PetscCall(VecFlag(x, mat->factorerrortype));
4134 if (mat->factorerrortype) {
4135 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4136 } else if (f) {
4137 PetscCall((*f)(mat, b, y, x));
4138 } else {
4139 /* do the solve then the add manually */
4140 if (x != y) {
4141 PetscCall(MatSolveTranspose(mat, b, x));
4142 PetscCall(VecAXPY(x, one, y));
4143 } else {
4144 PetscCall(VecDuplicate(x, &tmp));
4145 PetscCall(VecCopy(x, tmp));
4146 PetscCall(MatSolveTranspose(mat, b, x));
4147 PetscCall(VecAXPY(x, one, tmp));
4148 PetscCall(VecDestroy(&tmp));
4149 }
4150 }
4151 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4152 PetscCall(PetscObjectStateIncrease((PetscObject)x));
4153 PetscFunctionReturn(PETSC_SUCCESS);
4154 }
4155
4156 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4157 /*@
4158 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4159
4160 Neighbor-wise Collective
4161
4162 Input Parameters:
4163 + mat - the matrix
4164 . b - the right-hand side
4165 . omega - the relaxation factor
4166 . flag - flag indicating the type of SOR (see below)
4167 . shift - diagonal shift
4168 . its - the number of iterations
4169 - lits - the number of local iterations
4170
4171 Output Parameter:
4172 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4173
4174 SOR Flags:
4175 + `SOR_FORWARD_SWEEP` - forward SOR
4176 . `SOR_BACKWARD_SWEEP` - backward SOR
4177 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4178 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4179 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4180 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4181 . `SOR_EISENSTAT` - SOR with Eisenstat trick
4182 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies upper/lower triangular part of matrix to vector (with `omega`)
4183 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4184
4185 Level: developer
4186
4187 Notes:
4188 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4189 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4190 on each processor.
4191
4192 Application programmers will not generally use `MatSOR()` directly,
4193 but instead will employ `PCSOR` or `PCEISENSTAT`
4194
4195 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with inodes, this does a block SOR smoothing, otherwise it does a pointwise smoothing.
4196 For `MATAIJ` matrices with inodes, the block sizes are determined by the inode sizes, not the block size set with `MatSetBlockSize()`
4197
4198 Vectors `x` and `b` CANNOT be the same
4199
4200 The flags are implemented as bitwise inclusive or operations.
4201 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4202 to specify a zero initial guess for SSOR.
4203
4204 Developer Note:
4205 We should add block SOR support for `MATAIJ` matrices with block size set to greater than one and no inodes
4206
4207 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4208 @*/
MatSOR(Mat mat,Vec b,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec x)4209 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4210 {
4211 PetscFunctionBegin;
4212 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4213 PetscValidType(mat, 1);
4214 PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4215 PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4216 PetscCheckSameComm(mat, 1, b, 2);
4217 PetscCheckSameComm(mat, 1, x, 8);
4218 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4219 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4220 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
4221 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
4222 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
4223 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4224 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4225 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4226
4227 MatCheckPreallocated(mat, 1);
4228 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4229 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4230 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4231 PetscCall(PetscObjectStateIncrease((PetscObject)x));
4232 PetscFunctionReturn(PETSC_SUCCESS);
4233 }
4234
4235 /*
4236 Default matrix copy routine.
4237 */
MatCopy_Basic(Mat A,Mat B,MatStructure str)4238 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4239 {
4240 PetscInt i, rstart = 0, rend = 0, nz;
4241 const PetscInt *cwork;
4242 const PetscScalar *vwork;
4243
4244 PetscFunctionBegin;
4245 if (B->assembled) PetscCall(MatZeroEntries(B));
4246 if (str == SAME_NONZERO_PATTERN) {
4247 PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4248 for (i = rstart; i < rend; i++) {
4249 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4250 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4251 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4252 }
4253 } else {
4254 PetscCall(MatAYPX(B, 0.0, A, str));
4255 }
4256 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4257 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4258 PetscFunctionReturn(PETSC_SUCCESS);
4259 }
4260
4261 /*@
4262 MatCopy - Copies a matrix to another matrix.
4263
4264 Collective
4265
4266 Input Parameters:
4267 + A - the matrix
4268 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4269
4270 Output Parameter:
4271 . B - where the copy is put
4272
4273 Level: intermediate
4274
4275 Notes:
4276 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4277
4278 `MatCopy()` copies the matrix entries of a matrix to another existing
4279 matrix (after first zeroing the second matrix). A related routine is
4280 `MatConvert()`, which first creates a new matrix and then copies the data.
4281
4282 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4283 @*/
MatCopy(Mat A,Mat B,MatStructure str)4284 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4285 {
4286 PetscInt i;
4287
4288 PetscFunctionBegin;
4289 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4290 PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4291 PetscValidType(A, 1);
4292 PetscValidType(B, 2);
4293 PetscCheckSameComm(A, 1, B, 2);
4294 MatCheckPreallocated(B, 2);
4295 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4296 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4297 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")", A->rmap->N, B->rmap->N,
4298 A->cmap->N, B->cmap->N);
4299 MatCheckPreallocated(A, 1);
4300 if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4301
4302 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4303 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4304 else PetscCall(MatCopy_Basic(A, B, str));
4305
4306 B->stencil.dim = A->stencil.dim;
4307 B->stencil.noc = A->stencil.noc;
4308 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4309 B->stencil.dims[i] = A->stencil.dims[i];
4310 B->stencil.starts[i] = A->stencil.starts[i];
4311 }
4312
4313 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4314 PetscCall(PetscObjectStateIncrease((PetscObject)B));
4315 PetscFunctionReturn(PETSC_SUCCESS);
4316 }
4317
4318 /*@
4319 MatConvert - Converts a matrix to another matrix, either of the same
4320 or different type.
4321
4322 Collective
4323
4324 Input Parameters:
4325 + mat - the matrix
4326 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the
4327 same type as the original matrix.
4328 - reuse - denotes if the destination matrix is to be created or reused.
4329 Use `MAT_INPLACE_MATRIX` for inplace conversion (that is when you want the input `Mat` to be changed to contain the matrix in the new format), otherwise use
4330 `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` (can only be used after the first call was made with `MAT_INITIAL_MATRIX`, causes the matrix space in M to be reused).
4331
4332 Output Parameter:
4333 . M - pointer to place new matrix
4334
4335 Level: intermediate
4336
4337 Notes:
4338 `MatConvert()` first creates a new matrix and then copies the data from
4339 the first matrix. A related routine is `MatCopy()`, which copies the matrix
4340 entries of one matrix to another already existing matrix context.
4341
4342 Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4343 the MPI communicator of the generated matrix is always the same as the communicator
4344 of the input matrix.
4345
4346 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4347 @*/
MatConvert(Mat mat,MatType newtype,MatReuse reuse,Mat * M)4348 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4349 {
4350 PetscBool sametype, issame, flg;
4351 PetscBool3 issymmetric, ishermitian, isspd;
4352 char convname[256], mtype[256];
4353 Mat B;
4354
4355 PetscFunctionBegin;
4356 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4357 PetscValidType(mat, 1);
4358 PetscAssertPointer(M, 4);
4359 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4360 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4361 MatCheckPreallocated(mat, 1);
4362
4363 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4364 if (flg) newtype = mtype;
4365
4366 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4367 PetscCall(PetscStrcmp(newtype, "same", &issame));
4368 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4369 if (reuse == MAT_REUSE_MATRIX) {
4370 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4371 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4372 }
4373
4374 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4375 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4376 PetscFunctionReturn(PETSC_SUCCESS);
4377 }
4378
4379 /* Cache Mat options because some converters use MatHeaderReplace() */
4380 issymmetric = mat->symmetric;
4381 ishermitian = mat->hermitian;
4382 isspd = mat->spd;
4383
4384 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4385 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4386 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4387 } else {
4388 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4389 const char *prefix[3] = {"seq", "mpi", ""};
4390 PetscInt i;
4391 /*
4392 Order of precedence:
4393 0) See if newtype is a superclass of the current matrix.
4394 1) See if a specialized converter is known to the current matrix.
4395 2) See if a specialized converter is known to the desired matrix class.
4396 3) See if a good general converter is registered for the desired class
4397 (as of 6/27/03 only MATMPIADJ falls into this category).
4398 4) See if a good general converter is known for the current matrix.
4399 5) Use a really basic converter.
4400 */
4401
4402 /* 0) See if newtype is a superclass of the current matrix.
4403 i.e mat is mpiaij and newtype is aij */
4404 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4405 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4406 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4407 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4408 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4409 if (flg) {
4410 if (reuse == MAT_INPLACE_MATRIX) {
4411 PetscCall(PetscInfo(mat, "Early return\n"));
4412 PetscFunctionReturn(PETSC_SUCCESS);
4413 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4414 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4415 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4416 PetscFunctionReturn(PETSC_SUCCESS);
4417 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4418 PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4419 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4420 PetscFunctionReturn(PETSC_SUCCESS);
4421 }
4422 }
4423 }
4424 /* 1) See if a specialized converter is known to the current matrix and the desired class */
4425 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4426 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4427 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4428 PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4429 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4430 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4431 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4432 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4433 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4434 if (conv) goto foundconv;
4435 }
4436
4437 /* 2) See if a specialized converter is known to the desired matrix class. */
4438 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4439 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4440 PetscCall(MatSetType(B, newtype));
4441 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4442 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4443 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4444 PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4445 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4446 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4447 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4448 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4449 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4450 if (conv) {
4451 PetscCall(MatDestroy(&B));
4452 goto foundconv;
4453 }
4454 }
4455
4456 /* 3) See if a good general converter is registered for the desired class */
4457 conv = B->ops->convertfrom;
4458 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4459 PetscCall(MatDestroy(&B));
4460 if (conv) goto foundconv;
4461
4462 /* 4) See if a good general converter is known for the current matrix */
4463 if (mat->ops->convert) conv = mat->ops->convert;
4464 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4465 if (conv) goto foundconv;
4466
4467 /* 5) Use a really basic converter. */
4468 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4469 conv = MatConvert_Basic;
4470
4471 foundconv:
4472 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4473 PetscCall((*conv)(mat, newtype, reuse, M));
4474 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4475 /* the block sizes must be same if the mappings are copied over */
4476 (*M)->rmap->bs = mat->rmap->bs;
4477 (*M)->cmap->bs = mat->cmap->bs;
4478 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4479 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4480 (*M)->rmap->mapping = mat->rmap->mapping;
4481 (*M)->cmap->mapping = mat->cmap->mapping;
4482 }
4483 (*M)->stencil.dim = mat->stencil.dim;
4484 (*M)->stencil.noc = mat->stencil.noc;
4485 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4486 (*M)->stencil.dims[i] = mat->stencil.dims[i];
4487 (*M)->stencil.starts[i] = mat->stencil.starts[i];
4488 }
4489 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4490 }
4491 PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4492
4493 /* Reset Mat options */
4494 if (issymmetric != PETSC_BOOL3_UNKNOWN) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PetscBool3ToBool(issymmetric)));
4495 if (ishermitian != PETSC_BOOL3_UNKNOWN) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PetscBool3ToBool(ishermitian)));
4496 if (isspd != PETSC_BOOL3_UNKNOWN) PetscCall(MatSetOption(*M, MAT_SPD, PetscBool3ToBool(isspd)));
4497 PetscFunctionReturn(PETSC_SUCCESS);
4498 }
4499
4500 /*@
4501 MatFactorGetSolverType - Returns name of the package providing the factorization routines
4502
4503 Not Collective
4504
4505 Input Parameter:
4506 . mat - the matrix, must be a factored matrix
4507
4508 Output Parameter:
4509 . type - the string name of the package (do not free this string)
4510
4511 Level: intermediate
4512
4513 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4514 @*/
MatFactorGetSolverType(Mat mat,MatSolverType * type)4515 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4516 {
4517 PetscErrorCode (*conv)(Mat, MatSolverType *);
4518
4519 PetscFunctionBegin;
4520 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4521 PetscValidType(mat, 1);
4522 PetscAssertPointer(type, 2);
4523 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4524 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4525 if (conv) PetscCall((*conv)(mat, type));
4526 else *type = MATSOLVERPETSC;
4527 PetscFunctionReturn(PETSC_SUCCESS);
4528 }
4529
4530 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4531 struct _MatSolverTypeForSpecifcType {
4532 MatType mtype;
4533 /* no entry for MAT_FACTOR_NONE */
4534 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4535 MatSolverTypeForSpecifcType next;
4536 };
4537
4538 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4539 struct _MatSolverTypeHolder {
4540 char *name;
4541 MatSolverTypeForSpecifcType handlers;
4542 MatSolverTypeHolder next;
4543 };
4544
4545 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4546
4547 /*@C
4548 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4549
4550 Logically Collective, No Fortran Support
4551
4552 Input Parameters:
4553 + package - name of the package, for example `petsc` or `superlu`
4554 . mtype - the matrix type that works with this package
4555 . ftype - the type of factorization supported by the package
4556 - createfactor - routine that will create the factored matrix ready to be used
4557
4558 Level: developer
4559
4560 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4561 `MatGetFactor()`
4562 @*/
MatSolverTypeRegister(MatSolverType package,MatType mtype,MatFactorType ftype,PetscErrorCode (* createfactor)(Mat,MatFactorType,Mat *))4563 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4564 {
4565 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL;
4566 PetscBool flg;
4567 MatSolverTypeForSpecifcType inext, iprev = NULL;
4568
4569 PetscFunctionBegin;
4570 PetscCall(MatInitializePackage());
4571 if (!next) {
4572 PetscCall(PetscNew(&MatSolverTypeHolders));
4573 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4574 PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4575 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4576 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4577 PetscFunctionReturn(PETSC_SUCCESS);
4578 }
4579 while (next) {
4580 PetscCall(PetscStrcasecmp(package, next->name, &flg));
4581 if (flg) {
4582 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4583 inext = next->handlers;
4584 while (inext) {
4585 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4586 if (flg) {
4587 inext->createfactor[(int)ftype - 1] = createfactor;
4588 PetscFunctionReturn(PETSC_SUCCESS);
4589 }
4590 iprev = inext;
4591 inext = inext->next;
4592 }
4593 PetscCall(PetscNew(&iprev->next));
4594 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4595 iprev->next->createfactor[(int)ftype - 1] = createfactor;
4596 PetscFunctionReturn(PETSC_SUCCESS);
4597 }
4598 prev = next;
4599 next = next->next;
4600 }
4601 PetscCall(PetscNew(&prev->next));
4602 PetscCall(PetscStrallocpy(package, &prev->next->name));
4603 PetscCall(PetscNew(&prev->next->handlers));
4604 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4605 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4606 PetscFunctionReturn(PETSC_SUCCESS);
4607 }
4608
4609 /*@C
4610 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4611
4612 Input Parameters:
4613 + type - name of the package, for example `petsc` or `superlu`, if this is 'NULL', then the first result that satisfies the other criteria is returned
4614 . ftype - the type of factorization supported by the type
4615 - mtype - the matrix type that works with this type
4616
4617 Output Parameters:
4618 + foundtype - `PETSC_TRUE` if the type was registered
4619 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4620 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4621
4622 Calling sequence of `createfactor`:
4623 + A - the matrix providing the factor matrix
4624 . ftype - the `MatFactorType` of the factor requested
4625 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4626
4627 Level: developer
4628
4629 Note:
4630 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4631 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4632 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4633
4634 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4635 `MatInitializePackage()`
4636 @*/
MatSolverTypeGet(MatSolverType type,MatType mtype,MatFactorType ftype,PetscBool * foundtype,PetscBool * foundmtype,PetscErrorCode (** createfactor)(Mat A,MatFactorType ftype,Mat * B))4637 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4638 {
4639 MatSolverTypeHolder next = MatSolverTypeHolders;
4640 PetscBool flg;
4641 MatSolverTypeForSpecifcType inext;
4642
4643 PetscFunctionBegin;
4644 if (foundtype) *foundtype = PETSC_FALSE;
4645 if (foundmtype) *foundmtype = PETSC_FALSE;
4646 if (createfactor) *createfactor = NULL;
4647
4648 if (type) {
4649 while (next) {
4650 PetscCall(PetscStrcasecmp(type, next->name, &flg));
4651 if (flg) {
4652 if (foundtype) *foundtype = PETSC_TRUE;
4653 inext = next->handlers;
4654 while (inext) {
4655 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4656 if (flg) {
4657 if (foundmtype) *foundmtype = PETSC_TRUE;
4658 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4659 PetscFunctionReturn(PETSC_SUCCESS);
4660 }
4661 inext = inext->next;
4662 }
4663 }
4664 next = next->next;
4665 }
4666 } else {
4667 while (next) {
4668 inext = next->handlers;
4669 while (inext) {
4670 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4671 if (flg && inext->createfactor[(int)ftype - 1]) {
4672 if (foundtype) *foundtype = PETSC_TRUE;
4673 if (foundmtype) *foundmtype = PETSC_TRUE;
4674 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4675 PetscFunctionReturn(PETSC_SUCCESS);
4676 }
4677 inext = inext->next;
4678 }
4679 next = next->next;
4680 }
4681 /* try with base classes inext->mtype */
4682 next = MatSolverTypeHolders;
4683 while (next) {
4684 inext = next->handlers;
4685 while (inext) {
4686 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4687 if (flg && inext->createfactor[(int)ftype - 1]) {
4688 if (foundtype) *foundtype = PETSC_TRUE;
4689 if (foundmtype) *foundmtype = PETSC_TRUE;
4690 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4691 PetscFunctionReturn(PETSC_SUCCESS);
4692 }
4693 inext = inext->next;
4694 }
4695 next = next->next;
4696 }
4697 }
4698 PetscFunctionReturn(PETSC_SUCCESS);
4699 }
4700
MatSolverTypeDestroy(void)4701 PetscErrorCode MatSolverTypeDestroy(void)
4702 {
4703 MatSolverTypeHolder next = MatSolverTypeHolders, prev;
4704 MatSolverTypeForSpecifcType inext, iprev;
4705
4706 PetscFunctionBegin;
4707 while (next) {
4708 PetscCall(PetscFree(next->name));
4709 inext = next->handlers;
4710 while (inext) {
4711 PetscCall(PetscFree(inext->mtype));
4712 iprev = inext;
4713 inext = inext->next;
4714 PetscCall(PetscFree(iprev));
4715 }
4716 prev = next;
4717 next = next->next;
4718 PetscCall(PetscFree(prev));
4719 }
4720 MatSolverTypeHolders = NULL;
4721 PetscFunctionReturn(PETSC_SUCCESS);
4722 }
4723
4724 /*@
4725 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4726
4727 Logically Collective
4728
4729 Input Parameter:
4730 . mat - the matrix
4731
4732 Output Parameter:
4733 . flg - `PETSC_TRUE` if uses the ordering
4734
4735 Level: developer
4736
4737 Note:
4738 Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4739 packages do not, thus we want to skip generating the ordering when it is not needed or used.
4740
4741 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4742 @*/
MatFactorGetCanUseOrdering(Mat mat,PetscBool * flg)4743 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4744 {
4745 PetscFunctionBegin;
4746 *flg = mat->canuseordering;
4747 PetscFunctionReturn(PETSC_SUCCESS);
4748 }
4749
4750 /*@
4751 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4752
4753 Logically Collective
4754
4755 Input Parameters:
4756 + mat - the matrix obtained with `MatGetFactor()`
4757 - ftype - the factorization type to be used
4758
4759 Output Parameter:
4760 . otype - the preferred ordering type
4761
4762 Level: developer
4763
4764 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4765 @*/
MatFactorGetPreferredOrdering(Mat mat,MatFactorType ftype,MatOrderingType * otype)4766 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4767 {
4768 PetscFunctionBegin;
4769 *otype = mat->preferredordering[ftype];
4770 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4771 PetscFunctionReturn(PETSC_SUCCESS);
4772 }
4773
4774 /*@
4775 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4776
4777 Collective
4778
4779 Input Parameters:
4780 + mat - the matrix
4781 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's solver if it is available), if this is 'NULL', then the first result that satisfies
4782 the other criteria is returned
4783 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4784
4785 Output Parameter:
4786 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4787
4788 Options Database Keys:
4789 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers
4790 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device
4791 - -pc_factor_mat_solve_on_host <bool> - do mat solve on host (with device matrices). Default is doing it on device
4792
4793 Level: intermediate
4794
4795 Notes:
4796 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4797 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4798
4799 Users usually access the factorization solvers via `KSP`
4800
4801 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4802 such as pastix, superlu, mumps etc. PETSc must have been ./configure to use the external solver, using the option --download-package or --with-package-dir
4803
4804 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4805 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4806 For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4807
4808 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4809 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4810 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix.
4811
4812 Developer Note:
4813 This should actually be called `MatCreateFactor()` since it creates a new factor object
4814
4815 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4816 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4817 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4818 @*/
MatGetFactor(Mat mat,MatSolverType type,MatFactorType ftype,Mat * f)4819 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4820 {
4821 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4822 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4823
4824 PetscFunctionBegin;
4825 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4826 PetscValidType(mat, 1);
4827
4828 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4829 MatCheckPreallocated(mat, 1);
4830
4831 PetscCall(MatIsShell(mat, &shell));
4832 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4833 if (hasop) {
4834 PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4835 PetscFunctionReturn(PETSC_SUCCESS);
4836 }
4837
4838 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4839 if (!foundtype) {
4840 if (type) {
4841 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate solver type %s for factorization type %s and matrix type %s. Perhaps you must ./configure with --download-%s", type, MatFactorTypes[ftype],
4842 ((PetscObject)mat)->type_name, type);
4843 } else {
4844 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate a solver type for factorization type %s and matrix type %s.", MatFactorTypes[ftype], ((PetscObject)mat)->type_name);
4845 }
4846 }
4847 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4848 PetscCheck(conv, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support factorization type %s for matrix type %s", type, MatFactorTypes[ftype], ((PetscObject)mat)->type_name);
4849
4850 PetscCall((*conv)(mat, ftype, f));
4851 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4852 PetscFunctionReturn(PETSC_SUCCESS);
4853 }
4854
4855 /*@
4856 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4857
4858 Not Collective
4859
4860 Input Parameters:
4861 + mat - the matrix
4862 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default)
4863 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4864
4865 Output Parameter:
4866 . flg - PETSC_TRUE if the factorization is available
4867
4868 Level: intermediate
4869
4870 Notes:
4871 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4872 such as pastix, superlu, mumps etc.
4873
4874 PETSc must have been ./configure to use the external solver, using the option --download-package
4875
4876 Developer Note:
4877 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4878
4879 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4880 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4881 @*/
MatGetFactorAvailable(Mat mat,MatSolverType type,MatFactorType ftype,PetscBool * flg)4882 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4883 {
4884 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4885
4886 PetscFunctionBegin;
4887 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4888 PetscAssertPointer(flg, 4);
4889
4890 *flg = PETSC_FALSE;
4891 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4892
4893 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4894 MatCheckPreallocated(mat, 1);
4895
4896 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4897 *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4898 PetscFunctionReturn(PETSC_SUCCESS);
4899 }
4900
4901 /*@
4902 MatDuplicate - Duplicates a matrix including the non-zero structure.
4903
4904 Collective
4905
4906 Input Parameters:
4907 + mat - the matrix
4908 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4909 See the manual page for `MatDuplicateOption()` for an explanation of these options.
4910
4911 Output Parameter:
4912 . M - pointer to place new matrix
4913
4914 Level: intermediate
4915
4916 Notes:
4917 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4918
4919 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4920
4921 May be called with an unassembled input `Mat` if `MAT_DO_NOT_COPY_VALUES` is used, in which case the output `Mat` is unassembled as well.
4922
4923 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4924 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4925 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4926
4927 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4928 @*/
MatDuplicate(Mat mat,MatDuplicateOption op,Mat * M)4929 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4930 {
4931 Mat B;
4932 VecType vtype;
4933 PetscInt i;
4934 PetscObject dm, container_h, container_d;
4935 PetscErrorCodeFn *viewf;
4936
4937 PetscFunctionBegin;
4938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4939 PetscValidType(mat, 1);
4940 PetscAssertPointer(M, 3);
4941 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4942 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4943 MatCheckPreallocated(mat, 1);
4944
4945 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4946 PetscUseTypeMethod(mat, duplicate, op, M);
4947 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4948 B = *M;
4949
4950 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4951 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4952 PetscCall(MatGetVecType(mat, &vtype));
4953 PetscCall(MatSetVecType(B, vtype));
4954
4955 B->stencil.dim = mat->stencil.dim;
4956 B->stencil.noc = mat->stencil.noc;
4957 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4958 B->stencil.dims[i] = mat->stencil.dims[i];
4959 B->stencil.starts[i] = mat->stencil.starts[i];
4960 }
4961
4962 B->nooffproczerorows = mat->nooffproczerorows;
4963 B->nooffprocentries = mat->nooffprocentries;
4964
4965 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4966 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4967 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4968 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4969 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4970 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4971 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B));
4972 PetscCall(PetscObjectStateIncrease((PetscObject)B));
4973 PetscFunctionReturn(PETSC_SUCCESS);
4974 }
4975
4976 /*@
4977 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4978
4979 Logically Collective
4980
4981 Input Parameter:
4982 . mat - the matrix
4983
4984 Output Parameter:
4985 . v - the diagonal of the matrix
4986
4987 Level: intermediate
4988
4989 Note:
4990 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4991 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4992 is larger than `ndiag`, the values of the remaining entries are unspecified.
4993
4994 Currently only correct in parallel for square matrices.
4995
4996 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4997 @*/
MatGetDiagonal(Mat mat,Vec v)4998 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4999 {
5000 PetscFunctionBegin;
5001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5002 PetscValidType(mat, 1);
5003 PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5004 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5005 MatCheckPreallocated(mat, 1);
5006 if (PetscDefined(USE_DEBUG)) {
5007 PetscInt nv, row, col, ndiag;
5008
5009 PetscCall(VecGetLocalSize(v, &nv));
5010 PetscCall(MatGetLocalSize(mat, &row, &col));
5011 ndiag = PetscMin(row, col);
5012 PetscCheck(nv >= ndiag, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming Mat and Vec. Vec local size %" PetscInt_FMT " < Mat local diagonal length %" PetscInt_FMT, nv, ndiag);
5013 }
5014
5015 PetscUseTypeMethod(mat, getdiagonal, v);
5016 PetscCall(PetscObjectStateIncrease((PetscObject)v));
5017 PetscFunctionReturn(PETSC_SUCCESS);
5018 }
5019
5020 /*@
5021 MatGetRowMin - Gets the minimum value (of the real part) of each
5022 row of the matrix
5023
5024 Logically Collective
5025
5026 Input Parameter:
5027 . mat - the matrix
5028
5029 Output Parameters:
5030 + v - the vector for storing the maximums
5031 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5032
5033 Level: intermediate
5034
5035 Note:
5036 The result of this call are the same as if one converted the matrix to dense format
5037 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5038
5039 This code is only implemented for a couple of matrix formats.
5040
5041 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5042 `MatGetRowMax()`
5043 @*/
MatGetRowMin(Mat mat,Vec v,PetscInt idx[])5044 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5045 {
5046 PetscFunctionBegin;
5047 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5048 PetscValidType(mat, 1);
5049 PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5050 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5051
5052 if (!mat->cmap->N) {
5053 PetscCall(VecSet(v, PETSC_MAX_REAL));
5054 if (idx) {
5055 PetscInt i, m = mat->rmap->n;
5056 for (i = 0; i < m; i++) idx[i] = -1;
5057 }
5058 } else {
5059 MatCheckPreallocated(mat, 1);
5060 }
5061 PetscUseTypeMethod(mat, getrowmin, v, idx);
5062 PetscCall(PetscObjectStateIncrease((PetscObject)v));
5063 PetscFunctionReturn(PETSC_SUCCESS);
5064 }
5065
5066 /*@
5067 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5068 row of the matrix
5069
5070 Logically Collective
5071
5072 Input Parameter:
5073 . mat - the matrix
5074
5075 Output Parameters:
5076 + v - the vector for storing the minimums
5077 - idx - the indices of the column found for each row (or `NULL` if not needed)
5078
5079 Level: intermediate
5080
5081 Notes:
5082 if a row is completely empty or has only 0.0 values, then the `idx` value for that
5083 row is 0 (the first column).
5084
5085 This code is only implemented for a couple of matrix formats.
5086
5087 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5088 @*/
MatGetRowMinAbs(Mat mat,Vec v,PetscInt idx[])5089 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5090 {
5091 PetscFunctionBegin;
5092 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5093 PetscValidType(mat, 1);
5094 PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5095 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5096 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5097
5098 if (!mat->cmap->N) {
5099 PetscCall(VecSet(v, 0.0));
5100 if (idx) {
5101 PetscInt i, m = mat->rmap->n;
5102 for (i = 0; i < m; i++) idx[i] = -1;
5103 }
5104 } else {
5105 MatCheckPreallocated(mat, 1);
5106 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5107 PetscUseTypeMethod(mat, getrowminabs, v, idx);
5108 }
5109 PetscCall(PetscObjectStateIncrease((PetscObject)v));
5110 PetscFunctionReturn(PETSC_SUCCESS);
5111 }
5112
5113 /*@
5114 MatGetRowMax - Gets the maximum value (of the real part) of each
5115 row of the matrix
5116
5117 Logically Collective
5118
5119 Input Parameter:
5120 . mat - the matrix
5121
5122 Output Parameters:
5123 + v - the vector for storing the maximums
5124 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5125
5126 Level: intermediate
5127
5128 Notes:
5129 The result of this call are the same as if one converted the matrix to dense format
5130 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5131
5132 This code is only implemented for a couple of matrix formats.
5133
5134 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5135 @*/
MatGetRowMax(Mat mat,Vec v,PetscInt idx[])5136 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5137 {
5138 PetscFunctionBegin;
5139 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5140 PetscValidType(mat, 1);
5141 PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5142 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5143
5144 if (!mat->cmap->N) {
5145 PetscCall(VecSet(v, PETSC_MIN_REAL));
5146 if (idx) {
5147 PetscInt i, m = mat->rmap->n;
5148 for (i = 0; i < m; i++) idx[i] = -1;
5149 }
5150 } else {
5151 MatCheckPreallocated(mat, 1);
5152 PetscUseTypeMethod(mat, getrowmax, v, idx);
5153 }
5154 PetscCall(PetscObjectStateIncrease((PetscObject)v));
5155 PetscFunctionReturn(PETSC_SUCCESS);
5156 }
5157
5158 /*@
5159 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5160 row of the matrix
5161
5162 Logically Collective
5163
5164 Input Parameter:
5165 . mat - the matrix
5166
5167 Output Parameters:
5168 + v - the vector for storing the maximums
5169 - idx - the indices of the column found for each row (or `NULL` if not needed)
5170
5171 Level: intermediate
5172
5173 Notes:
5174 if a row is completely empty or has only 0.0 values, then the `idx` value for that
5175 row is 0 (the first column).
5176
5177 This code is only implemented for a couple of matrix formats.
5178
5179 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5180 @*/
MatGetRowMaxAbs(Mat mat,Vec v,PetscInt idx[])5181 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5182 {
5183 PetscFunctionBegin;
5184 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5185 PetscValidType(mat, 1);
5186 PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5187 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5188
5189 if (!mat->cmap->N) {
5190 PetscCall(VecSet(v, 0.0));
5191 if (idx) {
5192 PetscInt i, m = mat->rmap->n;
5193 for (i = 0; i < m; i++) idx[i] = -1;
5194 }
5195 } else {
5196 MatCheckPreallocated(mat, 1);
5197 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5198 PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5199 }
5200 PetscCall(PetscObjectStateIncrease((PetscObject)v));
5201 PetscFunctionReturn(PETSC_SUCCESS);
5202 }
5203
5204 /*@
5205 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5206
5207 Logically Collective
5208
5209 Input Parameter:
5210 . mat - the matrix
5211
5212 Output Parameter:
5213 . v - the vector for storing the sum
5214
5215 Level: intermediate
5216
5217 This code is only implemented for a couple of matrix formats.
5218
5219 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5220 @*/
MatGetRowSumAbs(Mat mat,Vec v)5221 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5222 {
5223 PetscFunctionBegin;
5224 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5225 PetscValidType(mat, 1);
5226 PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5227 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5228
5229 if (!mat->cmap->N) {
5230 PetscCall(VecSet(v, 0.0));
5231 } else {
5232 MatCheckPreallocated(mat, 1);
5233 PetscUseTypeMethod(mat, getrowsumabs, v);
5234 }
5235 PetscCall(PetscObjectStateIncrease((PetscObject)v));
5236 PetscFunctionReturn(PETSC_SUCCESS);
5237 }
5238
5239 /*@
5240 MatGetRowSum - Gets the sum of each row of the matrix
5241
5242 Logically or Neighborhood Collective
5243
5244 Input Parameter:
5245 . mat - the matrix
5246
5247 Output Parameter:
5248 . v - the vector for storing the sum of rows
5249
5250 Level: intermediate
5251
5252 Note:
5253 This code is slow since it is not currently specialized for different formats
5254
5255 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5256 @*/
MatGetRowSum(Mat mat,Vec v)5257 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5258 {
5259 Vec ones;
5260
5261 PetscFunctionBegin;
5262 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5263 PetscValidType(mat, 1);
5264 PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5265 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5266 MatCheckPreallocated(mat, 1);
5267 PetscCall(MatCreateVecs(mat, &ones, NULL));
5268 PetscCall(VecSet(ones, 1.));
5269 PetscCall(MatMult(mat, ones, v));
5270 PetscCall(VecDestroy(&ones));
5271 PetscFunctionReturn(PETSC_SUCCESS);
5272 }
5273
5274 /*@
5275 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5276 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5277
5278 Collective
5279
5280 Input Parameter:
5281 . mat - the matrix to provide the transpose
5282
5283 Output Parameter:
5284 . B - the matrix to contain the transpose; it MUST have the nonzero structure of the transpose of A or the code will crash or generate incorrect results
5285
5286 Level: advanced
5287
5288 Note:
5289 Normally the use of `MatTranspose`(A, `MAT_REUSE_MATRIX`, &B) requires that `B` was obtained with a call to `MatTranspose`(A, `MAT_INITIAL_MATRIX`, &B). This
5290 routine allows bypassing that call.
5291
5292 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5293 @*/
MatTransposeSetPrecursor(Mat mat,Mat B)5294 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5295 {
5296 MatParentState *rb = NULL;
5297
5298 PetscFunctionBegin;
5299 PetscCall(PetscNew(&rb));
5300 rb->id = ((PetscObject)mat)->id;
5301 rb->state = 0;
5302 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5303 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault));
5304 PetscFunctionReturn(PETSC_SUCCESS);
5305 }
5306
MatTranspose_Private(Mat mat,MatReuse reuse,Mat * B,PetscBool conjugate)5307 static PetscErrorCode MatTranspose_Private(Mat mat, MatReuse reuse, Mat *B, PetscBool conjugate)
5308 {
5309 PetscContainer rB = NULL;
5310 MatParentState *rb = NULL;
5311 PetscErrorCode (*f)(Mat, MatReuse, Mat *) = NULL;
5312
5313 PetscFunctionBegin;
5314 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5315 PetscValidType(mat, 1);
5316 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5317 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5318 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5319 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5320 MatCheckPreallocated(mat, 1);
5321 if (reuse == MAT_REUSE_MATRIX) {
5322 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5323 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5324 PetscCall(PetscContainerGetPointer(rB, &rb));
5325 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5326 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5327 }
5328
5329 if (conjugate) {
5330 f = mat->ops->hermitiantranspose;
5331 if (f) PetscCall((*f)(mat, reuse, B));
5332 }
5333 if (!f && !(reuse == MAT_INPLACE_MATRIX && mat->hermitian == PETSC_BOOL3_TRUE && conjugate)) {
5334 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5335 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5336 PetscUseTypeMethod(mat, transpose, reuse, B);
5337 PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5338 }
5339 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5340 if (conjugate) PetscCall(MatConjugate(*B));
5341 }
5342
5343 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5344 if (reuse != MAT_INPLACE_MATRIX) {
5345 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5346 PetscCall(PetscContainerGetPointer(rB, &rb));
5347 rb->state = ((PetscObject)mat)->state;
5348 rb->nonzerostate = mat->nonzerostate;
5349 }
5350 PetscFunctionReturn(PETSC_SUCCESS);
5351 }
5352
5353 /*@
5354 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place.
5355
5356 Collective
5357
5358 Input Parameters:
5359 + mat - the matrix to transpose
5360 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5361
5362 Output Parameter:
5363 . B - the transpose of the matrix
5364
5365 Level: intermediate
5366
5367 Notes:
5368 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5369
5370 `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX` to store the transpose. If you already have a matrix to contain the
5371 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5372
5373 If the nonzero structure of `mat` changed from the previous call to this function with the same matrices an error will be generated for some matrix types.
5374
5375 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed.
5376 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`.
5377
5378 If `mat` is unchanged from the last call this function returns immediately without recomputing the result
5379
5380 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()`
5381
5382 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5383 `MatTransposeSymbolic()`, `MatCreateTranspose()`
5384 @*/
MatTranspose(Mat mat,MatReuse reuse,Mat * B)5385 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5386 {
5387 PetscFunctionBegin;
5388 PetscCall(MatTranspose_Private(mat, reuse, B, PETSC_FALSE));
5389 PetscFunctionReturn(PETSC_SUCCESS);
5390 }
5391
5392 /*@
5393 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5394
5395 Collective
5396
5397 Input Parameter:
5398 . A - the matrix to transpose
5399
5400 Output Parameter:
5401 . B - the transpose. This is a complete matrix but the numerical portion is invalid. One can call `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) to compute the
5402 numerical portion.
5403
5404 Level: intermediate
5405
5406 Note:
5407 This is not supported for many matrix types, use `MatTranspose()` in those cases
5408
5409 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5410 @*/
MatTransposeSymbolic(Mat A,Mat * B)5411 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5412 {
5413 PetscFunctionBegin;
5414 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5415 PetscValidType(A, 1);
5416 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5417 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5418 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5419 PetscUseTypeMethod(A, transposesymbolic, B);
5420 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5421
5422 PetscCall(MatTransposeSetPrecursor(A, *B));
5423 PetscFunctionReturn(PETSC_SUCCESS);
5424 }
5425
MatTransposeCheckNonzeroState_Private(Mat A,Mat B)5426 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5427 {
5428 PetscContainer rB;
5429 MatParentState *rb;
5430
5431 PetscFunctionBegin;
5432 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5433 PetscValidType(A, 1);
5434 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5435 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5436 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5437 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5438 PetscCall(PetscContainerGetPointer(rB, &rb));
5439 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5440 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5441 PetscFunctionReturn(PETSC_SUCCESS);
5442 }
5443
5444 /*@
5445 MatIsTranspose - Test whether a matrix is another one's transpose,
5446 or its own, in which case it tests symmetry.
5447
5448 Collective
5449
5450 Input Parameters:
5451 + A - the matrix to test
5452 . B - the matrix to test against, this can equal the first parameter
5453 - tol - tolerance, differences between entries smaller than this are counted as zero
5454
5455 Output Parameter:
5456 . flg - the result
5457
5458 Level: intermediate
5459
5460 Notes:
5461 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5462 test involves parallel copies of the block off-diagonal parts of the matrix.
5463
5464 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5465 @*/
MatIsTranspose(Mat A,Mat B,PetscReal tol,PetscBool * flg)5466 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5467 {
5468 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5469
5470 PetscFunctionBegin;
5471 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5472 PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5473 PetscAssertPointer(flg, 4);
5474 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5475 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5476 *flg = PETSC_FALSE;
5477 if (f && g) {
5478 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5479 PetscCall((*f)(A, B, tol, flg));
5480 } else {
5481 MatType mattype;
5482
5483 PetscCall(MatGetType(f ? B : A, &mattype));
5484 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5485 }
5486 PetscFunctionReturn(PETSC_SUCCESS);
5487 }
5488
5489 /*@
5490 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5491
5492 Collective
5493
5494 Input Parameters:
5495 + mat - the matrix to transpose and complex conjugate
5496 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5497
5498 Output Parameter:
5499 . B - the Hermitian transpose
5500
5501 Level: intermediate
5502
5503 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5504 @*/
MatHermitianTranspose(Mat mat,MatReuse reuse,Mat * B)5505 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5506 {
5507 PetscFunctionBegin;
5508 PetscCall(MatTranspose_Private(mat, reuse, B, PETSC_TRUE));
5509 PetscFunctionReturn(PETSC_SUCCESS);
5510 }
5511
5512 /*@
5513 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5514
5515 Collective
5516
5517 Input Parameters:
5518 + A - the matrix to test
5519 . B - the matrix to test against, this can equal the first parameter
5520 - tol - tolerance, differences between entries smaller than this are counted as zero
5521
5522 Output Parameter:
5523 . flg - the result
5524
5525 Level: intermediate
5526
5527 Notes:
5528 Only available for `MATAIJ` matrices.
5529
5530 The sequential algorithm
5531 has a running time of the order of the number of nonzeros; the parallel
5532 test involves parallel copies of the block off-diagonal parts of the matrix.
5533
5534 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5535 @*/
MatIsHermitianTranspose(Mat A,Mat B,PetscReal tol,PetscBool * flg)5536 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5537 {
5538 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5539
5540 PetscFunctionBegin;
5541 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5542 PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5543 PetscAssertPointer(flg, 4);
5544 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5545 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5546 if (f && g) {
5547 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5548 PetscCall((*f)(A, B, tol, flg));
5549 } else {
5550 MatType mattype;
5551
5552 PetscCall(MatGetType(f ? B : A, &mattype));
5553 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for Hermitian transpose", mattype);
5554 }
5555 PetscFunctionReturn(PETSC_SUCCESS);
5556 }
5557
5558 /*@
5559 MatPermute - Creates a new matrix with rows and columns permuted from the
5560 original.
5561
5562 Collective
5563
5564 Input Parameters:
5565 + mat - the matrix to permute
5566 . row - row permutation, each processor supplies only the permutation for its rows
5567 - col - column permutation, each processor supplies only the permutation for its columns
5568
5569 Output Parameter:
5570 . B - the permuted matrix
5571
5572 Level: advanced
5573
5574 Note:
5575 The index sets map from row/col of permuted matrix to row/col of original matrix.
5576 The index sets should be on the same communicator as mat and have the same local sizes.
5577
5578 Developer Note:
5579 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5580 exploit the fact that row and col are permutations, consider implementing the
5581 more general `MatCreateSubMatrix()` instead.
5582
5583 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5584 @*/
MatPermute(Mat mat,IS row,IS col,Mat * B)5585 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5586 {
5587 PetscFunctionBegin;
5588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5589 PetscValidType(mat, 1);
5590 PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5591 PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5592 PetscAssertPointer(B, 4);
5593 PetscCheckSameComm(mat, 1, row, 2);
5594 if (row != col) PetscCheckSameComm(row, 2, col, 3);
5595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5596 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5597 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5598 MatCheckPreallocated(mat, 1);
5599
5600 if (mat->ops->permute) {
5601 PetscUseTypeMethod(mat, permute, row, col, B);
5602 PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5603 } else {
5604 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5605 }
5606 PetscFunctionReturn(PETSC_SUCCESS);
5607 }
5608
5609 /*@
5610 MatEqual - Compares two matrices.
5611
5612 Collective
5613
5614 Input Parameters:
5615 + A - the first matrix
5616 - B - the second matrix
5617
5618 Output Parameter:
5619 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5620
5621 Level: intermediate
5622
5623 Note:
5624 If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing
5625 the results of several matrix-vector product using randomly created vectors, see `MatMultEqual()`.
5626
5627 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()`
5628 @*/
MatEqual(Mat A,Mat B,PetscBool * flg)5629 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5630 {
5631 PetscFunctionBegin;
5632 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5633 PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5634 PetscValidType(A, 1);
5635 PetscValidType(B, 2);
5636 PetscAssertPointer(flg, 3);
5637 PetscCheckSameComm(A, 1, B, 2);
5638 MatCheckPreallocated(A, 1);
5639 MatCheckPreallocated(B, 2);
5640 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5641 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5642 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N,
5643 B->cmap->N);
5644 if (A->ops->equal && A->ops->equal == B->ops->equal) {
5645 PetscUseTypeMethod(A, equal, B, flg);
5646 } else {
5647 PetscCall(MatMultEqual(A, B, 10, flg));
5648 }
5649 PetscFunctionReturn(PETSC_SUCCESS);
5650 }
5651
5652 /*@
5653 MatDiagonalScale - Scales a matrix on the left and right by diagonal
5654 matrices that are stored as vectors. Either of the two scaling
5655 matrices can be `NULL`.
5656
5657 Collective
5658
5659 Input Parameters:
5660 + mat - the matrix to be scaled
5661 . l - the left scaling vector (or `NULL`)
5662 - r - the right scaling vector (or `NULL`)
5663
5664 Level: intermediate
5665
5666 Note:
5667 `MatDiagonalScale()` computes $A = LAR$, where
5668 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5669 The L scales the rows of the matrix, the R scales the columns of the matrix.
5670
5671 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5672 @*/
MatDiagonalScale(Mat mat,Vec l,Vec r)5673 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5674 {
5675 PetscBool flg = PETSC_FALSE;
5676
5677 PetscFunctionBegin;
5678 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5679 PetscValidType(mat, 1);
5680 if (l) {
5681 PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5682 PetscCheckSameComm(mat, 1, l, 2);
5683 }
5684 if (r) {
5685 PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5686 PetscCheckSameComm(mat, 1, r, 3);
5687 }
5688 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5689 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5690 MatCheckPreallocated(mat, 1);
5691 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5692
5693 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5694 PetscUseTypeMethod(mat, diagonalscale, l, r);
5695 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5696 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5697 if (l != r && (PetscBool3ToBool(mat->symmetric) || PetscBool3ToBool(mat->hermitian))) {
5698 if (!PetscDefined(USE_COMPLEX) || PetscBool3ToBool(mat->symmetric)) {
5699 if (l && r) PetscCall(VecEqual(l, r, &flg));
5700 if (!flg) {
5701 PetscCall(PetscObjectTypeCompareAny((PetscObject)mat, &flg, MATSEQSBAIJ, MATMPISBAIJ, ""));
5702 PetscCheck(!flg, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "For symmetric format, left and right scaling vectors must be the same");
5703 mat->symmetric = mat->spd = PETSC_BOOL3_FALSE;
5704 if (!PetscDefined(USE_COMPLEX)) mat->hermitian = PETSC_BOOL3_FALSE;
5705 else mat->hermitian = PETSC_BOOL3_UNKNOWN;
5706 }
5707 }
5708 if (PetscDefined(USE_COMPLEX) && PetscBool3ToBool(mat->hermitian)) {
5709 flg = PETSC_FALSE;
5710 if (l && r) {
5711 Vec conjugate;
5712
5713 PetscCall(VecDuplicate(l, &conjugate));
5714 PetscCall(VecCopy(l, conjugate));
5715 PetscCall(VecConjugate(conjugate));
5716 PetscCall(VecEqual(conjugate, r, &flg));
5717 PetscCall(VecDestroy(&conjugate));
5718 }
5719 if (!flg) {
5720 PetscCall(PetscObjectTypeCompareAny((PetscObject)mat, &flg, MATSEQSBAIJ, MATMPISBAIJ, ""));
5721 PetscCheck(!flg, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "For symmetric format and Hermitian matrix, left and right scaling vectors must be conjugate one of the other");
5722 mat->hermitian = PETSC_BOOL3_FALSE;
5723 mat->symmetric = mat->spd = PETSC_BOOL3_UNKNOWN;
5724 }
5725 }
5726 }
5727 PetscFunctionReturn(PETSC_SUCCESS);
5728 }
5729
5730 /*@
5731 MatScale - Scales all elements of a matrix by a given number.
5732
5733 Logically Collective
5734
5735 Input Parameters:
5736 + mat - the matrix to be scaled
5737 - a - the scaling value
5738
5739 Level: intermediate
5740
5741 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5742 @*/
MatScale(Mat mat,PetscScalar a)5743 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5744 {
5745 PetscFunctionBegin;
5746 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5747 PetscValidType(mat, 1);
5748 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5749 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5750 PetscValidLogicalCollectiveScalar(mat, a, 2);
5751 MatCheckPreallocated(mat, 1);
5752
5753 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5754 if (a != (PetscScalar)1.0) {
5755 PetscUseTypeMethod(mat, scale, a);
5756 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5757 }
5758 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5759 PetscFunctionReturn(PETSC_SUCCESS);
5760 }
5761
5762 /*@
5763 MatNorm - Calculates various norms of a matrix.
5764
5765 Collective
5766
5767 Input Parameters:
5768 + mat - the matrix
5769 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5770
5771 Output Parameter:
5772 . nrm - the resulting norm
5773
5774 Level: intermediate
5775
5776 .seealso: [](ch_matrices), `Mat`
5777 @*/
MatNorm(Mat mat,NormType type,PetscReal * nrm)5778 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5779 {
5780 PetscFunctionBegin;
5781 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5782 PetscValidType(mat, 1);
5783 PetscAssertPointer(nrm, 3);
5784
5785 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5786 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5787 MatCheckPreallocated(mat, 1);
5788
5789 PetscUseTypeMethod(mat, norm, type, nrm);
5790 PetscFunctionReturn(PETSC_SUCCESS);
5791 }
5792
5793 /*
5794 This variable is used to prevent counting of MatAssemblyBegin() that
5795 are called from within a MatAssemblyEnd().
5796 */
5797 static PetscInt MatAssemblyEnd_InUse = 0;
5798 /*@
5799 MatAssemblyBegin - Begins assembling the matrix. This routine should
5800 be called after completing all calls to `MatSetValues()`.
5801
5802 Collective
5803
5804 Input Parameters:
5805 + mat - the matrix
5806 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5807
5808 Level: beginner
5809
5810 Notes:
5811 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to
5812 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5813
5814 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5815 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5816 using the matrix.
5817
5818 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5819 same flag of `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` for all processes. Thus you CANNOT locally change from `ADD_VALUES` to `INSERT_VALUES`, that is
5820 a global collective operation requiring all processes that share the matrix.
5821
5822 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5823 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5824 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5825
5826 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5827 @*/
MatAssemblyBegin(Mat mat,MatAssemblyType type)5828 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5829 {
5830 PetscFunctionBegin;
5831 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5832 PetscValidType(mat, 1);
5833 MatCheckPreallocated(mat, 1);
5834 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5835 if (mat->assembled) {
5836 mat->was_assembled = PETSC_TRUE;
5837 mat->assembled = PETSC_FALSE;
5838 }
5839
5840 if (!MatAssemblyEnd_InUse) {
5841 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5842 PetscTryTypeMethod(mat, assemblybegin, type);
5843 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5844 } else PetscTryTypeMethod(mat, assemblybegin, type);
5845 PetscFunctionReturn(PETSC_SUCCESS);
5846 }
5847
5848 /*@
5849 MatAssembled - Indicates if a matrix has been assembled and is ready for
5850 use; for example, in matrix-vector product.
5851
5852 Not Collective
5853
5854 Input Parameter:
5855 . mat - the matrix
5856
5857 Output Parameter:
5858 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5859
5860 Level: advanced
5861
5862 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5863 @*/
MatAssembled(Mat mat,PetscBool * assembled)5864 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5865 {
5866 PetscFunctionBegin;
5867 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5868 PetscAssertPointer(assembled, 2);
5869 *assembled = mat->assembled;
5870 PetscFunctionReturn(PETSC_SUCCESS);
5871 }
5872
5873 /*@
5874 MatAssemblyEnd - Completes assembling the matrix. This routine should
5875 be called after `MatAssemblyBegin()`.
5876
5877 Collective
5878
5879 Input Parameters:
5880 + mat - the matrix
5881 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5882
5883 Options Database Keys:
5884 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5885 . -mat_view ::ascii_info_detail - Prints more detailed info
5886 . -mat_view - Prints matrix in ASCII format
5887 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format
5888 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5889 . -display <name> - Sets display name (default is host)
5890 . -draw_pause <sec> - Sets number of seconds to pause after display
5891 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5892 . -viewer_socket_machine <machine> - Machine to use for socket
5893 . -viewer_socket_port <port> - Port number to use for socket
5894 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5895
5896 Level: beginner
5897
5898 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5899 @*/
MatAssemblyEnd(Mat mat,MatAssemblyType type)5900 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5901 {
5902 static PetscInt inassm = 0;
5903 PetscBool flg = PETSC_FALSE;
5904
5905 PetscFunctionBegin;
5906 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5907 PetscValidType(mat, 1);
5908
5909 inassm++;
5910 MatAssemblyEnd_InUse++;
5911 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5912 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5913 PetscTryTypeMethod(mat, assemblyend, type);
5914 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5915 } else PetscTryTypeMethod(mat, assemblyend, type);
5916
5917 /* Flush assembly is not a true assembly */
5918 if (type != MAT_FLUSH_ASSEMBLY) {
5919 if (mat->num_ass) {
5920 if (!mat->symmetry_eternal) {
5921 mat->symmetric = PETSC_BOOL3_UNKNOWN;
5922 mat->hermitian = PETSC_BOOL3_UNKNOWN;
5923 }
5924 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5925 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5926 }
5927 mat->num_ass++;
5928 mat->assembled = PETSC_TRUE;
5929 mat->ass_nonzerostate = mat->nonzerostate;
5930 }
5931
5932 mat->insertmode = NOT_SET_VALUES;
5933 MatAssemblyEnd_InUse--;
5934 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5935 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5936 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5937
5938 if (mat->checksymmetryonassembly) {
5939 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5940 if (flg) {
5941 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5942 } else {
5943 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5944 }
5945 }
5946 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5947 }
5948 inassm--;
5949 PetscFunctionReturn(PETSC_SUCCESS);
5950 }
5951
5952 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5953 /*@
5954 MatSetOption - Sets a parameter option for a matrix. Some options
5955 may be specific to certain storage formats. Some options
5956 determine how values will be inserted (or added). Sorted,
5957 row-oriented input will generally assemble the fastest. The default
5958 is row-oriented.
5959
5960 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5961
5962 Input Parameters:
5963 + mat - the matrix
5964 . op - the option, one of those listed below (and possibly others),
5965 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5966
5967 Options Describing Matrix Structure:
5968 + `MAT_SPD` - symmetric positive definite
5969 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5970 . `MAT_HERMITIAN` - transpose is the complex conjugation
5971 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5972 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5973 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5974 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5975
5976 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5977 do not need to be computed (usually at a high cost)
5978
5979 Options For Use with `MatSetValues()`:
5980 Insert a logically dense subblock, which can be
5981 . `MAT_ROW_ORIENTED` - row-oriented (default)
5982
5983 These options reflect the data you pass in with `MatSetValues()`; it has
5984 nothing to do with how the data is stored internally in the matrix
5985 data structure.
5986
5987 When (re)assembling a matrix, we can restrict the input for
5988 efficiency/debugging purposes. These options include
5989 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5990 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5991 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5992 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5993 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5994 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5995 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5996 performance for very large process counts.
5997 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5998 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5999 functions, instead sending only neighbor messages.
6000
6001 Level: intermediate
6002
6003 Notes:
6004 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
6005
6006 Some options are relevant only for particular matrix types and
6007 are thus ignored by others. Other options are not supported by
6008 certain matrix types and will generate an error message if set.
6009
6010 If using Fortran to compute a matrix, one may need to
6011 use the column-oriented option (or convert to the row-oriented
6012 format).
6013
6014 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
6015 that would generate a new entry in the nonzero structure is instead
6016 ignored. Thus, if memory has not already been allocated for this particular
6017 data, then the insertion is ignored. For dense matrices, in which
6018 the entire array is allocated, no entries are ever ignored.
6019 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6020
6021 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
6022 that would generate a new entry in the nonzero structure instead produces
6023 an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats only.) If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6024
6025 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
6026 that would generate a new entry that has not been preallocated will
6027 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
6028 only.) This is a useful flag when debugging matrix memory preallocation.
6029 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6030
6031 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
6032 other processors should be dropped, rather than stashed.
6033 This is useful if you know that the "owning" processor is also
6034 always generating the correct matrix entries, so that PETSc need
6035 not transfer duplicate entries generated on another processor.
6036
6037 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6038 searches during matrix assembly. When this flag is set, the hash table
6039 is created during the first matrix assembly. This hash table is
6040 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6041 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6042 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6043 supported by `MATMPIBAIJ` format only.
6044
6045 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6046 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6047
6048 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6049 a zero location in the matrix
6050
6051 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6052
6053 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6054 zero row routines and thus improves performance for very large process counts.
6055
6056 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6057 part of the matrix (since they should match the upper triangular part).
6058
6059 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6060 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6061 with finite difference schemes with non-periodic boundary conditions.
6062
6063 Developer Note:
6064 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6065 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6066 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6067 not changed.
6068
6069 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6070 @*/
MatSetOption(Mat mat,MatOption op,PetscBool flg)6071 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6072 {
6073 PetscFunctionBegin;
6074 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6075 if (op > 0) {
6076 PetscValidLogicalCollectiveEnum(mat, op, 2);
6077 PetscValidLogicalCollectiveBool(mat, flg, 3);
6078 }
6079
6080 PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op);
6081
6082 switch (op) {
6083 case MAT_FORCE_DIAGONAL_ENTRIES:
6084 mat->force_diagonals = flg;
6085 PetscFunctionReturn(PETSC_SUCCESS);
6086 case MAT_NO_OFF_PROC_ENTRIES:
6087 mat->nooffprocentries = flg;
6088 PetscFunctionReturn(PETSC_SUCCESS);
6089 case MAT_SUBSET_OFF_PROC_ENTRIES:
6090 mat->assembly_subset = flg;
6091 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6092 #if !defined(PETSC_HAVE_MPIUNI)
6093 PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6094 #endif
6095 mat->stash.first_assembly_done = PETSC_FALSE;
6096 }
6097 PetscFunctionReturn(PETSC_SUCCESS);
6098 case MAT_NO_OFF_PROC_ZERO_ROWS:
6099 mat->nooffproczerorows = flg;
6100 PetscFunctionReturn(PETSC_SUCCESS);
6101 case MAT_SPD:
6102 if (flg) {
6103 mat->spd = PETSC_BOOL3_TRUE;
6104 mat->symmetric = PETSC_BOOL3_TRUE;
6105 mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6106 #if !defined(PETSC_USE_COMPLEX)
6107 mat->hermitian = PETSC_BOOL3_TRUE;
6108 #endif
6109 } else {
6110 mat->spd = PETSC_BOOL3_FALSE;
6111 }
6112 break;
6113 case MAT_SYMMETRIC:
6114 mat->symmetric = PetscBoolToBool3(flg);
6115 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6116 #if !defined(PETSC_USE_COMPLEX)
6117 mat->hermitian = PetscBoolToBool3(flg);
6118 #endif
6119 break;
6120 case MAT_HERMITIAN:
6121 mat->hermitian = PetscBoolToBool3(flg);
6122 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6123 #if !defined(PETSC_USE_COMPLEX)
6124 mat->symmetric = PetscBoolToBool3(flg);
6125 #endif
6126 break;
6127 case MAT_STRUCTURALLY_SYMMETRIC:
6128 mat->structurally_symmetric = PetscBoolToBool3(flg);
6129 break;
6130 case MAT_SYMMETRY_ETERNAL:
6131 PetscCheck(mat->symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SYMMETRY_ETERNAL without first setting MAT_SYMMETRIC to true or false");
6132 mat->symmetry_eternal = flg;
6133 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6134 break;
6135 case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6136 PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURALLY_SYMMETRIC to true or false");
6137 mat->structural_symmetry_eternal = flg;
6138 break;
6139 case MAT_SPD_ETERNAL:
6140 PetscCheck(mat->spd != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SPD_ETERNAL without first setting MAT_SPD to true or false");
6141 mat->spd_eternal = flg;
6142 if (flg) {
6143 mat->structural_symmetry_eternal = PETSC_TRUE;
6144 mat->symmetry_eternal = PETSC_TRUE;
6145 }
6146 break;
6147 case MAT_STRUCTURE_ONLY:
6148 mat->structure_only = flg;
6149 break;
6150 case MAT_SORTED_FULL:
6151 mat->sortedfull = flg;
6152 break;
6153 default:
6154 break;
6155 }
6156 PetscTryTypeMethod(mat, setoption, op, flg);
6157 PetscFunctionReturn(PETSC_SUCCESS);
6158 }
6159
6160 /*@
6161 MatGetOption - Gets a parameter option that has been set for a matrix.
6162
6163 Logically Collective
6164
6165 Input Parameters:
6166 + mat - the matrix
6167 - op - the option, this only responds to certain options, check the code for which ones
6168
6169 Output Parameter:
6170 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6171
6172 Level: intermediate
6173
6174 Notes:
6175 Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6176
6177 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6178 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6179
6180 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6181 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6182 @*/
MatGetOption(Mat mat,MatOption op,PetscBool * flg)6183 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6184 {
6185 PetscFunctionBegin;
6186 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6187 PetscValidType(mat, 1);
6188
6189 PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op);
6190 PetscCheck(((PetscObject)mat)->type_name, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_TYPENOTSET, "Cannot get options until type and size have been set, see MatSetType() and MatSetSizes()");
6191
6192 switch (op) {
6193 case MAT_NO_OFF_PROC_ENTRIES:
6194 *flg = mat->nooffprocentries;
6195 break;
6196 case MAT_NO_OFF_PROC_ZERO_ROWS:
6197 *flg = mat->nooffproczerorows;
6198 break;
6199 case MAT_SYMMETRIC:
6200 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6201 break;
6202 case MAT_HERMITIAN:
6203 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6204 break;
6205 case MAT_STRUCTURALLY_SYMMETRIC:
6206 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6207 break;
6208 case MAT_SPD:
6209 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6210 break;
6211 case MAT_SYMMETRY_ETERNAL:
6212 *flg = mat->symmetry_eternal;
6213 break;
6214 case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6215 *flg = mat->symmetry_eternal;
6216 break;
6217 default:
6218 break;
6219 }
6220 PetscFunctionReturn(PETSC_SUCCESS);
6221 }
6222
6223 /*@
6224 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices
6225 this routine retains the old nonzero structure.
6226
6227 Logically Collective
6228
6229 Input Parameter:
6230 . mat - the matrix
6231
6232 Level: intermediate
6233
6234 Note:
6235 If the matrix was not preallocated then a default, likely poor preallocation will be set in the matrix, so this should be called after the preallocation phase.
6236 See the Performance chapter of the users manual for information on preallocating matrices.
6237
6238 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6239 @*/
MatZeroEntries(Mat mat)6240 PetscErrorCode MatZeroEntries(Mat mat)
6241 {
6242 PetscFunctionBegin;
6243 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6244 PetscValidType(mat, 1);
6245 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6246 PetscCheck(mat->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for matrices where you have set values but not yet assembled");
6247 MatCheckPreallocated(mat, 1);
6248
6249 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6250 PetscUseTypeMethod(mat, zeroentries);
6251 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6252 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6253 PetscFunctionReturn(PETSC_SUCCESS);
6254 }
6255
6256 /*@
6257 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6258 of a set of rows and columns of a matrix.
6259
6260 Collective
6261
6262 Input Parameters:
6263 + mat - the matrix
6264 . numRows - the number of rows/columns to zero
6265 . rows - the global row indices
6266 . diag - value put in the diagonal of the eliminated rows
6267 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6268 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries
6269
6270 Level: intermediate
6271
6272 Notes:
6273 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6274
6275 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6276 The other entries of `b` will be adjusted by the known values of `x` times the corresponding matrix entries in the columns that are being eliminated
6277
6278 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6279 Krylov method to take advantage of the known solution on the zeroed rows.
6280
6281 For the parallel case, all processes that share the matrix (i.e.,
6282 those in the communicator used for matrix creation) MUST call this
6283 routine, regardless of whether any rows being zeroed are owned by
6284 them.
6285
6286 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6287 removes them from the nonzero pattern. The nonzero pattern of the matrix can still change if a nonzero needs to be inserted on a diagonal entry that was previously
6288 missing.
6289
6290 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6291 list only rows local to itself).
6292
6293 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6294
6295 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6296 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6297 @*/
MatZeroRowsColumns(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)6298 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6299 {
6300 PetscFunctionBegin;
6301 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6302 PetscValidType(mat, 1);
6303 if (numRows) PetscAssertPointer(rows, 3);
6304 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6305 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6306 MatCheckPreallocated(mat, 1);
6307
6308 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6309 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6310 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6311 PetscFunctionReturn(PETSC_SUCCESS);
6312 }
6313
6314 /*@
6315 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6316 of a set of rows and columns of a matrix.
6317
6318 Collective
6319
6320 Input Parameters:
6321 + mat - the matrix
6322 . is - the rows to zero
6323 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6324 . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6325 - b - optional vector of right-hand side, that will be adjusted by provided solution
6326
6327 Level: intermediate
6328
6329 Note:
6330 See `MatZeroRowsColumns()` for details on how this routine operates.
6331
6332 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6333 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6334 @*/
MatZeroRowsColumnsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)6335 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6336 {
6337 PetscInt numRows;
6338 const PetscInt *rows;
6339
6340 PetscFunctionBegin;
6341 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6342 PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6343 PetscValidType(mat, 1);
6344 PetscValidType(is, 2);
6345 PetscCall(ISGetLocalSize(is, &numRows));
6346 PetscCall(ISGetIndices(is, &rows));
6347 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6348 PetscCall(ISRestoreIndices(is, &rows));
6349 PetscFunctionReturn(PETSC_SUCCESS);
6350 }
6351
6352 /*@
6353 MatZeroRows - Zeros all entries (except possibly the main diagonal)
6354 of a set of rows of a matrix.
6355
6356 Collective
6357
6358 Input Parameters:
6359 + mat - the matrix
6360 . numRows - the number of rows to zero
6361 . rows - the global row indices
6362 . diag - value put in the diagonal of the zeroed rows
6363 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6364 - b - optional vector of right-hand side, that will be adjusted by provided solution entries
6365
6366 Level: intermediate
6367
6368 Notes:
6369 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6370
6371 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6372
6373 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6374 Krylov method to take advantage of the known solution on the zeroed rows.
6375
6376 May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reduced problem (`PCDISTRIBUTE` completely eliminates the zeroed rows and their corresponding columns)
6377 from the matrix.
6378
6379 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6380 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense
6381 formats this does not alter the nonzero structure.
6382
6383 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6384 of the matrix is not changed the values are
6385 merely zeroed.
6386
6387 The user can set a value in the diagonal entry (or for the `MATAIJ` format
6388 formats can optionally remove the main diagonal entry from the
6389 nonzero structure as well, by passing 0.0 as the final argument).
6390
6391 For the parallel case, all processes that share the matrix (i.e.,
6392 those in the communicator used for matrix creation) MUST call this
6393 routine, regardless of whether any rows being zeroed are owned by
6394 them.
6395
6396 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6397 list only rows local to itself).
6398
6399 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6400 owns that are to be zeroed. This saves a global synchronization in the implementation.
6401
6402 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6403 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6404 @*/
MatZeroRows(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)6405 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6406 {
6407 PetscFunctionBegin;
6408 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6409 PetscValidType(mat, 1);
6410 if (numRows) PetscAssertPointer(rows, 3);
6411 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6412 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6413 MatCheckPreallocated(mat, 1);
6414
6415 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6416 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6417 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6418 PetscFunctionReturn(PETSC_SUCCESS);
6419 }
6420
6421 /*@
6422 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6423 of a set of rows of a matrix indicated by an `IS`
6424
6425 Collective
6426
6427 Input Parameters:
6428 + mat - the matrix
6429 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed)
6430 . diag - value put in all diagonals of eliminated rows
6431 . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6432 - b - optional vector of right-hand side, that will be adjusted by provided solution
6433
6434 Level: intermediate
6435
6436 Note:
6437 See `MatZeroRows()` for details on how this routine operates.
6438
6439 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6440 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS`
6441 @*/
MatZeroRowsIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)6442 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6443 {
6444 PetscInt numRows = 0;
6445 const PetscInt *rows = NULL;
6446
6447 PetscFunctionBegin;
6448 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6449 PetscValidType(mat, 1);
6450 if (is) {
6451 PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6452 PetscCall(ISGetLocalSize(is, &numRows));
6453 PetscCall(ISGetIndices(is, &rows));
6454 }
6455 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6456 if (is) PetscCall(ISRestoreIndices(is, &rows));
6457 PetscFunctionReturn(PETSC_SUCCESS);
6458 }
6459
6460 /*@
6461 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6462 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process.
6463
6464 Collective
6465
6466 Input Parameters:
6467 + mat - the matrix
6468 . numRows - the number of rows to remove
6469 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil`
6470 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6471 . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6472 - b - optional vector of right-hand side, that will be adjusted by provided solution
6473
6474 Level: intermediate
6475
6476 Notes:
6477 See `MatZeroRows()` for details on how this routine operates.
6478
6479 The grid coordinates are across the entire grid, not just the local portion
6480
6481 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6482 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6483 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6484 `DM_BOUNDARY_PERIODIC` boundary type.
6485
6486 For indices that don't mean anything for your case (like the `k` index when working in 2d) or the `c` index when you have
6487 a single value per point) you can skip filling those indices.
6488
6489 Fortran Note:
6490 `idxm` and `idxn` should be declared as
6491 .vb
6492 MatStencil idxm(4, m)
6493 .ve
6494 and the values inserted using
6495 .vb
6496 idxm(MatStencil_i, 1) = i
6497 idxm(MatStencil_j, 1) = j
6498 idxm(MatStencil_k, 1) = k
6499 idxm(MatStencil_c, 1) = c
6500 etc
6501 .ve
6502
6503 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6504 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6505 @*/
MatZeroRowsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)6506 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6507 {
6508 PetscInt dim = mat->stencil.dim;
6509 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc);
6510 PetscInt *dims = mat->stencil.dims + 1;
6511 PetscInt *starts = mat->stencil.starts;
6512 PetscInt *dxm = (PetscInt *)rows;
6513 PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6514
6515 PetscFunctionBegin;
6516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6517 PetscValidType(mat, 1);
6518 if (numRows) PetscAssertPointer(rows, 3);
6519
6520 PetscCall(PetscMalloc1(numRows, &jdxm));
6521 for (i = 0; i < numRows; ++i) {
6522 /* Skip unused dimensions (they are ordered k, j, i, c) */
6523 for (j = 0; j < 3 - sdim; ++j) dxm++;
6524 /* Local index in X dir */
6525 tmp = *dxm++ - starts[0];
6526 /* Loop over remaining dimensions */
6527 for (j = 0; j < dim - 1; ++j) {
6528 /* If nonlocal, set index to be negative */
6529 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6530 /* Update local index */
6531 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6532 }
6533 /* Skip component slot if necessary */
6534 if (mat->stencil.noc) dxm++;
6535 /* Local row number */
6536 if (tmp >= 0) jdxm[numNewRows++] = tmp;
6537 }
6538 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6539 PetscCall(PetscFree(jdxm));
6540 PetscFunctionReturn(PETSC_SUCCESS);
6541 }
6542
6543 /*@
6544 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6545 of a set of rows and columns of a matrix.
6546
6547 Collective
6548
6549 Input Parameters:
6550 + mat - the matrix
6551 . numRows - the number of rows/columns to remove
6552 . rows - the grid coordinates (and component number when dof > 1) for matrix rows
6553 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6554 . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6555 - b - optional vector of right-hand side, that will be adjusted by provided solution
6556
6557 Level: intermediate
6558
6559 Notes:
6560 See `MatZeroRowsColumns()` for details on how this routine operates.
6561
6562 The grid coordinates are across the entire grid, not just the local portion
6563
6564 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6565 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6566 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6567 `DM_BOUNDARY_PERIODIC` boundary type.
6568
6569 For indices that don't mean anything for your case (like the `k` index when working in 2d) or the `c` index when you have
6570 a single value per point) you can skip filling those indices.
6571
6572 Fortran Note:
6573 `idxm` and `idxn` should be declared as
6574 .vb
6575 MatStencil idxm(4, m)
6576 .ve
6577 and the values inserted using
6578 .vb
6579 idxm(MatStencil_i, 1) = i
6580 idxm(MatStencil_j, 1) = j
6581 idxm(MatStencil_k, 1) = k
6582 idxm(MatStencil_c, 1) = c
6583 etc
6584 .ve
6585
6586 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6587 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6588 @*/
MatZeroRowsColumnsStencil(Mat mat,PetscInt numRows,const MatStencil rows[],PetscScalar diag,Vec x,Vec b)6589 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6590 {
6591 PetscInt dim = mat->stencil.dim;
6592 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc);
6593 PetscInt *dims = mat->stencil.dims + 1;
6594 PetscInt *starts = mat->stencil.starts;
6595 PetscInt *dxm = (PetscInt *)rows;
6596 PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6597
6598 PetscFunctionBegin;
6599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6600 PetscValidType(mat, 1);
6601 if (numRows) PetscAssertPointer(rows, 3);
6602
6603 PetscCall(PetscMalloc1(numRows, &jdxm));
6604 for (i = 0; i < numRows; ++i) {
6605 /* Skip unused dimensions (they are ordered k, j, i, c) */
6606 for (j = 0; j < 3 - sdim; ++j) dxm++;
6607 /* Local index in X dir */
6608 tmp = *dxm++ - starts[0];
6609 /* Loop over remaining dimensions */
6610 for (j = 0; j < dim - 1; ++j) {
6611 /* If nonlocal, set index to be negative */
6612 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6613 /* Update local index */
6614 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6615 }
6616 /* Skip component slot if necessary */
6617 if (mat->stencil.noc) dxm++;
6618 /* Local row number */
6619 if (tmp >= 0) jdxm[numNewRows++] = tmp;
6620 }
6621 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6622 PetscCall(PetscFree(jdxm));
6623 PetscFunctionReturn(PETSC_SUCCESS);
6624 }
6625
6626 /*@
6627 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6628 of a set of rows of a matrix; using local numbering of rows.
6629
6630 Collective
6631
6632 Input Parameters:
6633 + mat - the matrix
6634 . numRows - the number of rows to remove
6635 . rows - the local row indices
6636 . diag - value put in all diagonals of eliminated rows
6637 . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6638 - b - optional vector of right-hand side, that will be adjusted by provided solution
6639
6640 Level: intermediate
6641
6642 Notes:
6643 Before calling `MatZeroRowsLocal()`, the user must first set the
6644 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6645
6646 See `MatZeroRows()` for details on how this routine operates.
6647
6648 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6649 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6650 @*/
MatZeroRowsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)6651 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6652 {
6653 PetscFunctionBegin;
6654 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6655 PetscValidType(mat, 1);
6656 if (numRows) PetscAssertPointer(rows, 3);
6657 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6658 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6659 MatCheckPreallocated(mat, 1);
6660
6661 if (mat->ops->zerorowslocal) {
6662 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6663 } else {
6664 IS is, newis;
6665 PetscInt *newRows, nl = 0;
6666
6667 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6668 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_USE_POINTER, &is));
6669 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6670 PetscCall(ISGetIndices(newis, (const PetscInt **)&newRows));
6671 for (PetscInt i = 0; i < numRows; i++)
6672 if (newRows[i] > -1) newRows[nl++] = newRows[i];
6673 PetscUseTypeMethod(mat, zerorows, nl, newRows, diag, x, b);
6674 PetscCall(ISRestoreIndices(newis, (const PetscInt **)&newRows));
6675 PetscCall(ISDestroy(&newis));
6676 PetscCall(ISDestroy(&is));
6677 }
6678 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6679 PetscFunctionReturn(PETSC_SUCCESS);
6680 }
6681
6682 /*@
6683 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6684 of a set of rows of a matrix; using local numbering of rows.
6685
6686 Collective
6687
6688 Input Parameters:
6689 + mat - the matrix
6690 . is - index set of rows to remove
6691 . diag - value put in all diagonals of eliminated rows
6692 . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6693 - b - optional vector of right-hand side, that will be adjusted by provided solution
6694
6695 Level: intermediate
6696
6697 Notes:
6698 Before calling `MatZeroRowsLocalIS()`, the user must first set the
6699 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6700
6701 See `MatZeroRows()` for details on how this routine operates.
6702
6703 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6704 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6705 @*/
MatZeroRowsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)6706 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6707 {
6708 PetscInt numRows;
6709 const PetscInt *rows;
6710
6711 PetscFunctionBegin;
6712 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6713 PetscValidType(mat, 1);
6714 PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6715 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6716 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6717 MatCheckPreallocated(mat, 1);
6718
6719 PetscCall(ISGetLocalSize(is, &numRows));
6720 PetscCall(ISGetIndices(is, &rows));
6721 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6722 PetscCall(ISRestoreIndices(is, &rows));
6723 PetscFunctionReturn(PETSC_SUCCESS);
6724 }
6725
6726 /*@
6727 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6728 of a set of rows and columns of a matrix; using local numbering of rows.
6729
6730 Collective
6731
6732 Input Parameters:
6733 + mat - the matrix
6734 . numRows - the number of rows to remove
6735 . rows - the global row indices
6736 . diag - value put in all diagonals of eliminated rows
6737 . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6738 - b - optional vector of right-hand side, that will be adjusted by provided solution
6739
6740 Level: intermediate
6741
6742 Notes:
6743 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6744 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6745
6746 See `MatZeroRowsColumns()` for details on how this routine operates.
6747
6748 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6749 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6750 @*/
MatZeroRowsColumnsLocal(Mat mat,PetscInt numRows,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)6751 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6752 {
6753 PetscFunctionBegin;
6754 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6755 PetscValidType(mat, 1);
6756 if (numRows) PetscAssertPointer(rows, 3);
6757 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6758 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6759 MatCheckPreallocated(mat, 1);
6760
6761 if (mat->ops->zerorowscolumnslocal) {
6762 PetscUseTypeMethod(mat, zerorowscolumnslocal, numRows, rows, diag, x, b);
6763 } else {
6764 IS is, newis;
6765 PetscInt *newRows, nl = 0;
6766
6767 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6768 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_USE_POINTER, &is));
6769 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6770 PetscCall(ISGetIndices(newis, (const PetscInt **)&newRows));
6771 for (PetscInt i = 0; i < numRows; i++)
6772 if (newRows[i] > -1) newRows[nl++] = newRows[i];
6773 PetscUseTypeMethod(mat, zerorowscolumns, nl, newRows, diag, x, b);
6774 PetscCall(ISRestoreIndices(newis, (const PetscInt **)&newRows));
6775 PetscCall(ISDestroy(&newis));
6776 PetscCall(ISDestroy(&is));
6777 }
6778 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6779 PetscFunctionReturn(PETSC_SUCCESS);
6780 }
6781
6782 /*@
6783 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6784 of a set of rows and columns of a matrix; using local numbering of rows.
6785
6786 Collective
6787
6788 Input Parameters:
6789 + mat - the matrix
6790 . is - index set of rows to remove
6791 . diag - value put in all diagonals of eliminated rows
6792 . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6793 - b - optional vector of right-hand side, that will be adjusted by provided solution
6794
6795 Level: intermediate
6796
6797 Notes:
6798 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6799 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6800
6801 See `MatZeroRowsColumns()` for details on how this routine operates.
6802
6803 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6804 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6805 @*/
MatZeroRowsColumnsLocalIS(Mat mat,IS is,PetscScalar diag,Vec x,Vec b)6806 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6807 {
6808 PetscInt numRows;
6809 const PetscInt *rows;
6810
6811 PetscFunctionBegin;
6812 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6813 PetscValidType(mat, 1);
6814 PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6815 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6816 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6817 MatCheckPreallocated(mat, 1);
6818
6819 PetscCall(ISGetLocalSize(is, &numRows));
6820 PetscCall(ISGetIndices(is, &rows));
6821 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6822 PetscCall(ISRestoreIndices(is, &rows));
6823 PetscFunctionReturn(PETSC_SUCCESS);
6824 }
6825
6826 /*@
6827 MatGetSize - Returns the numbers of rows and columns in a matrix.
6828
6829 Not Collective
6830
6831 Input Parameter:
6832 . mat - the matrix
6833
6834 Output Parameters:
6835 + m - the number of global rows
6836 - n - the number of global columns
6837
6838 Level: beginner
6839
6840 Note:
6841 Both output parameters can be `NULL` on input.
6842
6843 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6844 @*/
MatGetSize(Mat mat,PetscInt * m,PetscInt * n)6845 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6846 {
6847 PetscFunctionBegin;
6848 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6849 if (m) *m = mat->rmap->N;
6850 if (n) *n = mat->cmap->N;
6851 PetscFunctionReturn(PETSC_SUCCESS);
6852 }
6853
6854 /*@
6855 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6856 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6857
6858 Not Collective
6859
6860 Input Parameter:
6861 . mat - the matrix
6862
6863 Output Parameters:
6864 + m - the number of local rows, use `NULL` to not obtain this value
6865 - n - the number of local columns, use `NULL` to not obtain this value
6866
6867 Level: beginner
6868
6869 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6870 @*/
MatGetLocalSize(Mat mat,PetscInt * m,PetscInt * n)6871 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6872 {
6873 PetscFunctionBegin;
6874 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6875 if (m) PetscAssertPointer(m, 2);
6876 if (n) PetscAssertPointer(n, 3);
6877 if (m) *m = mat->rmap->n;
6878 if (n) *n = mat->cmap->n;
6879 PetscFunctionReturn(PETSC_SUCCESS);
6880 }
6881
6882 /*@
6883 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6884 vector one multiplies this matrix by that are owned by this processor.
6885
6886 Not Collective, unless matrix has not been allocated, then collective
6887
6888 Input Parameter:
6889 . mat - the matrix
6890
6891 Output Parameters:
6892 + m - the global index of the first local column, use `NULL` to not obtain this value
6893 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6894
6895 Level: developer
6896
6897 Notes:
6898 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6899
6900 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6901 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6902
6903 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6904 the local values in the matrix.
6905
6906 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6907 Layouts](sec_matlayout) for details on matrix layouts.
6908
6909 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6910 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6911 @*/
MatGetOwnershipRangeColumn(Mat mat,PetscInt * m,PetscInt * n)6912 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6913 {
6914 PetscFunctionBegin;
6915 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6916 PetscValidType(mat, 1);
6917 if (m) PetscAssertPointer(m, 2);
6918 if (n) PetscAssertPointer(n, 3);
6919 MatCheckPreallocated(mat, 1);
6920 if (m) *m = mat->cmap->rstart;
6921 if (n) *n = mat->cmap->rend;
6922 PetscFunctionReturn(PETSC_SUCCESS);
6923 }
6924
6925 /*@
6926 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6927 this MPI process.
6928
6929 Not Collective
6930
6931 Input Parameter:
6932 . mat - the matrix
6933
6934 Output Parameters:
6935 + m - the global index of the first local row, use `NULL` to not obtain this value
6936 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6937
6938 Level: beginner
6939
6940 Notes:
6941 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6942
6943 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6944 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6945
6946 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6947 the local values in the matrix.
6948
6949 The high argument is one more than the last element stored locally.
6950
6951 For all matrices it returns the range of matrix rows associated with rows of a vector that
6952 would contain the result of a matrix vector product with this matrix. See [Matrix
6953 Layouts](sec_matlayout) for details on matrix layouts.
6954
6955 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6956 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6957 @*/
MatGetOwnershipRange(Mat mat,PetscInt * m,PetscInt * n)6958 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6959 {
6960 PetscFunctionBegin;
6961 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6962 PetscValidType(mat, 1);
6963 if (m) PetscAssertPointer(m, 2);
6964 if (n) PetscAssertPointer(n, 3);
6965 MatCheckPreallocated(mat, 1);
6966 if (m) *m = mat->rmap->rstart;
6967 if (n) *n = mat->rmap->rend;
6968 PetscFunctionReturn(PETSC_SUCCESS);
6969 }
6970
6971 /*@C
6972 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6973 `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6974
6975 Not Collective, unless matrix has not been allocated
6976
6977 Input Parameter:
6978 . mat - the matrix
6979
6980 Output Parameter:
6981 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6982 where `size` is the number of MPI processes used by `mat`
6983
6984 Level: beginner
6985
6986 Notes:
6987 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6988
6989 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6990 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6991
6992 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6993 the local values in the matrix.
6994
6995 For all matrices it returns the ranges of matrix rows associated with rows of a vector that
6996 would contain the result of a matrix vector product with this matrix. See [Matrix
6997 Layouts](sec_matlayout) for details on matrix layouts.
6998
6999 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
7000 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
7001 `DMDAGetGhostCorners()`, `DM`
7002 @*/
MatGetOwnershipRanges(Mat mat,const PetscInt * ranges[])7003 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
7004 {
7005 PetscFunctionBegin;
7006 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7007 PetscValidType(mat, 1);
7008 MatCheckPreallocated(mat, 1);
7009 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
7010 PetscFunctionReturn(PETSC_SUCCESS);
7011 }
7012
7013 /*@C
7014 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
7015 vector one multiplies this vector by that are owned by each processor.
7016
7017 Not Collective, unless matrix has not been allocated
7018
7019 Input Parameter:
7020 . mat - the matrix
7021
7022 Output Parameter:
7023 . ranges - start of each processors portion plus one more than the total length at the end
7024
7025 Level: beginner
7026
7027 Notes:
7028 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
7029
7030 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
7031 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
7032
7033 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
7034 the local values in the matrix.
7035
7036 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
7037 Layouts](sec_matlayout) for details on matrix layouts.
7038
7039 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
7040 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
7041 `DMDAGetGhostCorners()`, `DM`
7042 @*/
MatGetOwnershipRangesColumn(Mat mat,const PetscInt * ranges[])7043 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
7044 {
7045 PetscFunctionBegin;
7046 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7047 PetscValidType(mat, 1);
7048 MatCheckPreallocated(mat, 1);
7049 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
7050 PetscFunctionReturn(PETSC_SUCCESS);
7051 }
7052
7053 /*@
7054 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7055
7056 Not Collective
7057
7058 Input Parameter:
7059 . A - matrix
7060
7061 Output Parameters:
7062 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7063 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7064
7065 Level: intermediate
7066
7067 Note:
7068 You should call `ISDestroy()` on the returned `IS`
7069
7070 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7071 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7072 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7073 details on matrix layouts.
7074
7075 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7076 @*/
MatGetOwnershipIS(Mat A,IS * rows,IS * cols)7077 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7078 {
7079 PetscErrorCode (*f)(Mat, IS *, IS *);
7080
7081 PetscFunctionBegin;
7082 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7083 PetscValidType(A, 1);
7084 MatCheckPreallocated(A, 1);
7085 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7086 if (f) {
7087 PetscCall((*f)(A, rows, cols));
7088 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7089 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7090 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7091 }
7092 PetscFunctionReturn(PETSC_SUCCESS);
7093 }
7094
7095 /*@
7096 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7097 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7098 to complete the factorization.
7099
7100 Collective
7101
7102 Input Parameters:
7103 + fact - the factorized matrix obtained with `MatGetFactor()`
7104 . mat - the matrix
7105 . row - row permutation
7106 . col - column permutation
7107 - info - structure containing
7108 .vb
7109 levels - number of levels of fill.
7110 expected fill - as ratio of original fill.
7111 1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7112 missing diagonal entries)
7113 .ve
7114
7115 Level: developer
7116
7117 Notes:
7118 See [Matrix Factorization](sec_matfactor) for additional information.
7119
7120 Most users should employ the `KSP` interface for linear solvers
7121 instead of working directly with matrix algebra routines such as this.
7122 See, e.g., `KSPCreate()`.
7123
7124 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7125
7126 Fortran Note:
7127 A valid (non-null) `info` argument must be provided
7128
7129 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7130 `MatGetOrdering()`, `MatFactorInfo`
7131 @*/
MatILUFactorSymbolic(Mat fact,Mat mat,IS row,IS col,const MatFactorInfo * info)7132 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7133 {
7134 PetscFunctionBegin;
7135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7136 PetscValidType(mat, 2);
7137 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7138 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7139 PetscAssertPointer(info, 5);
7140 PetscAssertPointer(fact, 1);
7141 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7142 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7143 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7144 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7145 MatCheckPreallocated(mat, 2);
7146
7147 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7148 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7149 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7150 PetscFunctionReturn(PETSC_SUCCESS);
7151 }
7152
7153 /*@
7154 MatICCFactorSymbolic - Performs symbolic incomplete
7155 Cholesky factorization for a symmetric matrix. Use
7156 `MatCholeskyFactorNumeric()` to complete the factorization.
7157
7158 Collective
7159
7160 Input Parameters:
7161 + fact - the factorized matrix obtained with `MatGetFactor()`
7162 . mat - the matrix to be factored
7163 . perm - row and column permutation
7164 - info - structure containing
7165 .vb
7166 levels - number of levels of fill.
7167 expected fill - as ratio of original fill.
7168 .ve
7169
7170 Level: developer
7171
7172 Notes:
7173 Most users should employ the `KSP` interface for linear solvers
7174 instead of working directly with matrix algebra routines such as this.
7175 See, e.g., `KSPCreate()`.
7176
7177 This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7178
7179 Fortran Note:
7180 A valid (non-null) `info` argument must be provided
7181
7182 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7183 @*/
MatICCFactorSymbolic(Mat fact,Mat mat,IS perm,const MatFactorInfo * info)7184 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7185 {
7186 PetscFunctionBegin;
7187 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7188 PetscValidType(mat, 2);
7189 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7190 PetscAssertPointer(info, 4);
7191 PetscAssertPointer(fact, 1);
7192 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7193 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7194 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7195 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7196 MatCheckPreallocated(mat, 2);
7197
7198 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7199 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7200 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7201 PetscFunctionReturn(PETSC_SUCCESS);
7202 }
7203
7204 /*@C
7205 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7206 points to an array of valid matrices, they may be reused to store the new
7207 submatrices.
7208
7209 Collective
7210
7211 Input Parameters:
7212 + mat - the matrix
7213 . n - the number of submatrixes to be extracted (on this processor, may be zero)
7214 . irow - index set of rows to extract
7215 . icol - index set of columns to extract
7216 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7217
7218 Output Parameter:
7219 . submat - the array of submatrices
7220
7221 Level: advanced
7222
7223 Notes:
7224 `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7225 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7226 to extract a parallel submatrix.
7227
7228 Some matrix types place restrictions on the row and column
7229 indices, such as that they be sorted or that they be equal to each other.
7230
7231 The index sets may not have duplicate entries.
7232
7233 When extracting submatrices from a parallel matrix, each processor can
7234 form a different submatrix by setting the rows and columns of its
7235 individual index sets according to the local submatrix desired.
7236
7237 When finished using the submatrices, the user should destroy
7238 them with `MatDestroySubMatrices()`.
7239
7240 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7241 original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7242
7243 This routine creates the matrices in submat; you should NOT create them before
7244 calling it. It also allocates the array of matrix pointers submat.
7245
7246 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7247 request one row/column in a block, they must request all rows/columns that are in
7248 that block. For example, if the block size is 2 you cannot request just row 0 and
7249 column 0.
7250
7251 Fortran Note:
7252 .vb
7253 Mat, pointer :: submat(:)
7254 .ve
7255
7256 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7257 @*/
MatCreateSubMatrices(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat * submat[])7258 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7259 {
7260 PetscInt i;
7261 PetscBool eq;
7262
7263 PetscFunctionBegin;
7264 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7265 PetscValidType(mat, 1);
7266 if (n) {
7267 PetscAssertPointer(irow, 3);
7268 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7269 PetscAssertPointer(icol, 4);
7270 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7271 }
7272 PetscAssertPointer(submat, 6);
7273 if (n && scall == MAT_REUSE_MATRIX) {
7274 PetscAssertPointer(*submat, 6);
7275 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7276 }
7277 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7278 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7279 MatCheckPreallocated(mat, 1);
7280 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7281 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7282 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7283 for (i = 0; i < n; i++) {
7284 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7285 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7286 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7287 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7288 if (mat->boundtocpu && mat->bindingpropagates) {
7289 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7290 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7291 }
7292 #endif
7293 }
7294 PetscFunctionReturn(PETSC_SUCCESS);
7295 }
7296
7297 /*@C
7298 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms).
7299
7300 Collective
7301
7302 Input Parameters:
7303 + mat - the matrix
7304 . n - the number of submatrixes to be extracted
7305 . irow - index set of rows to extract
7306 . icol - index set of columns to extract
7307 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7308
7309 Output Parameter:
7310 . submat - the array of submatrices
7311
7312 Level: advanced
7313
7314 Note:
7315 This is used by `PCGASM`
7316
7317 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7318 @*/
MatCreateSubMatricesMPI(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat * submat[])7319 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7320 {
7321 PetscInt i;
7322 PetscBool eq;
7323
7324 PetscFunctionBegin;
7325 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7326 PetscValidType(mat, 1);
7327 if (n) {
7328 PetscAssertPointer(irow, 3);
7329 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7330 PetscAssertPointer(icol, 4);
7331 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7332 }
7333 PetscAssertPointer(submat, 6);
7334 if (n && scall == MAT_REUSE_MATRIX) {
7335 PetscAssertPointer(*submat, 6);
7336 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7337 }
7338 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7339 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7340 MatCheckPreallocated(mat, 1);
7341
7342 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7343 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7344 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7345 for (i = 0; i < n; i++) {
7346 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7347 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7348 }
7349 PetscFunctionReturn(PETSC_SUCCESS);
7350 }
7351
7352 /*@C
7353 MatDestroyMatrices - Destroys an array of matrices
7354
7355 Collective
7356
7357 Input Parameters:
7358 + n - the number of local matrices
7359 - mat - the matrices (this is a pointer to the array of matrices)
7360
7361 Level: advanced
7362
7363 Notes:
7364 Frees not only the matrices, but also the array that contains the matrices
7365
7366 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7367
7368 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7369 @*/
MatDestroyMatrices(PetscInt n,Mat * mat[])7370 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7371 {
7372 PetscInt i;
7373
7374 PetscFunctionBegin;
7375 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7376 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7377 PetscAssertPointer(mat, 2);
7378
7379 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7380
7381 /* memory is allocated even if n = 0 */
7382 PetscCall(PetscFree(*mat));
7383 PetscFunctionReturn(PETSC_SUCCESS);
7384 }
7385
7386 /*@C
7387 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7388
7389 Collective
7390
7391 Input Parameters:
7392 + n - the number of local matrices
7393 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`)
7394
7395 Level: advanced
7396
7397 Note:
7398 Frees not only the matrices, but also the array that contains the matrices
7399
7400 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7401 @*/
MatDestroySubMatrices(PetscInt n,Mat * mat[])7402 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7403 {
7404 Mat mat0;
7405
7406 PetscFunctionBegin;
7407 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7408 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7409 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7410 PetscAssertPointer(mat, 2);
7411
7412 mat0 = (*mat)[0];
7413 if (mat0 && mat0->ops->destroysubmatrices) {
7414 PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7415 } else {
7416 PetscCall(MatDestroyMatrices(n, mat));
7417 }
7418 PetscFunctionReturn(PETSC_SUCCESS);
7419 }
7420
7421 /*@
7422 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7423
7424 Collective
7425
7426 Input Parameter:
7427 . mat - the matrix
7428
7429 Output Parameter:
7430 . matstruct - the sequential matrix with the nonzero structure of `mat`
7431
7432 Level: developer
7433
7434 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7435 @*/
MatGetSeqNonzeroStructure(Mat mat,Mat * matstruct)7436 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7437 {
7438 PetscFunctionBegin;
7439 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7440 PetscAssertPointer(matstruct, 2);
7441
7442 PetscValidType(mat, 1);
7443 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7444 MatCheckPreallocated(mat, 1);
7445
7446 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7447 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7448 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7449 PetscFunctionReturn(PETSC_SUCCESS);
7450 }
7451
7452 /*@C
7453 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7454
7455 Collective
7456
7457 Input Parameter:
7458 . mat - the matrix
7459
7460 Level: advanced
7461
7462 Note:
7463 This is not needed, one can just call `MatDestroy()`
7464
7465 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7466 @*/
MatDestroySeqNonzeroStructure(Mat * mat)7467 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7468 {
7469 PetscFunctionBegin;
7470 PetscAssertPointer(mat, 1);
7471 PetscCall(MatDestroy(mat));
7472 PetscFunctionReturn(PETSC_SUCCESS);
7473 }
7474
7475 /*@
7476 MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7477 replaces the index sets by larger ones that represent submatrices with
7478 additional overlap.
7479
7480 Collective
7481
7482 Input Parameters:
7483 + mat - the matrix
7484 . n - the number of index sets
7485 . is - the array of index sets (these index sets will changed during the call)
7486 - ov - the additional overlap requested
7487
7488 Options Database Key:
7489 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7490
7491 Level: developer
7492
7493 Note:
7494 The computed overlap preserves the matrix block sizes when the blocks are square.
7495 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7496 that block are included in the overlap regardless of whether each specific column would increase the overlap.
7497
7498 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7499 @*/
MatIncreaseOverlap(Mat mat,PetscInt n,IS is[],PetscInt ov)7500 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7501 {
7502 PetscInt i, bs, cbs;
7503
7504 PetscFunctionBegin;
7505 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7506 PetscValidType(mat, 1);
7507 PetscValidLogicalCollectiveInt(mat, n, 2);
7508 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7509 if (n) {
7510 PetscAssertPointer(is, 3);
7511 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7512 }
7513 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7514 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7515 MatCheckPreallocated(mat, 1);
7516
7517 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7518 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7519 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7520 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7521 PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7522 if (bs == cbs) {
7523 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7524 }
7525 PetscFunctionReturn(PETSC_SUCCESS);
7526 }
7527
7528 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7529
7530 /*@
7531 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7532 a sub communicator, replaces the index sets by larger ones that represent submatrices with
7533 additional overlap.
7534
7535 Collective
7536
7537 Input Parameters:
7538 + mat - the matrix
7539 . n - the number of index sets
7540 . is - the array of index sets (these index sets will changed during the call)
7541 - ov - the additional overlap requested
7542
7543 ` Options Database Key:
7544 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7545
7546 Level: developer
7547
7548 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7549 @*/
MatIncreaseOverlapSplit(Mat mat,PetscInt n,IS is[],PetscInt ov)7550 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7551 {
7552 PetscInt i;
7553
7554 PetscFunctionBegin;
7555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7556 PetscValidType(mat, 1);
7557 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7558 if (n) {
7559 PetscAssertPointer(is, 3);
7560 PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7561 }
7562 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7563 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7564 MatCheckPreallocated(mat, 1);
7565 if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7566 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7567 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7568 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7569 PetscFunctionReturn(PETSC_SUCCESS);
7570 }
7571
7572 /*@
7573 MatGetBlockSize - Returns the matrix block size.
7574
7575 Not Collective
7576
7577 Input Parameter:
7578 . mat - the matrix
7579
7580 Output Parameter:
7581 . bs - block size
7582
7583 Level: intermediate
7584
7585 Notes:
7586 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7587
7588 If the block size has not been set yet this routine returns 1.
7589
7590 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7591 @*/
MatGetBlockSize(Mat mat,PetscInt * bs)7592 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7593 {
7594 PetscFunctionBegin;
7595 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7596 PetscAssertPointer(bs, 2);
7597 *bs = mat->rmap->bs;
7598 PetscFunctionReturn(PETSC_SUCCESS);
7599 }
7600
7601 /*@
7602 MatGetBlockSizes - Returns the matrix block row and column sizes.
7603
7604 Not Collective
7605
7606 Input Parameter:
7607 . mat - the matrix
7608
7609 Output Parameters:
7610 + rbs - row block size
7611 - cbs - column block size
7612
7613 Level: intermediate
7614
7615 Notes:
7616 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7617 If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7618
7619 If a block size has not been set yet this routine returns 1.
7620
7621 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7622 @*/
MatGetBlockSizes(Mat mat,PetscInt * rbs,PetscInt * cbs)7623 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7624 {
7625 PetscFunctionBegin;
7626 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7627 if (rbs) PetscAssertPointer(rbs, 2);
7628 if (cbs) PetscAssertPointer(cbs, 3);
7629 if (rbs) *rbs = mat->rmap->bs;
7630 if (cbs) *cbs = mat->cmap->bs;
7631 PetscFunctionReturn(PETSC_SUCCESS);
7632 }
7633
7634 /*@
7635 MatSetBlockSize - Sets the matrix block size.
7636
7637 Logically Collective
7638
7639 Input Parameters:
7640 + mat - the matrix
7641 - bs - block size
7642
7643 Level: intermediate
7644
7645 Notes:
7646 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7647 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7648
7649 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7650 is compatible with the matrix local sizes.
7651
7652 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7653 @*/
MatSetBlockSize(Mat mat,PetscInt bs)7654 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7655 {
7656 PetscFunctionBegin;
7657 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7658 PetscValidLogicalCollectiveInt(mat, bs, 2);
7659 PetscCall(MatSetBlockSizes(mat, bs, bs));
7660 PetscFunctionReturn(PETSC_SUCCESS);
7661 }
7662
7663 typedef struct {
7664 PetscInt n;
7665 IS *is;
7666 Mat *mat;
7667 PetscObjectState nonzerostate;
7668 Mat C;
7669 } EnvelopeData;
7670
EnvelopeDataDestroy(PetscCtxRt ptr)7671 static PetscErrorCode EnvelopeDataDestroy(PetscCtxRt ptr)
7672 {
7673 EnvelopeData *edata = *(EnvelopeData **)ptr;
7674
7675 PetscFunctionBegin;
7676 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7677 PetscCall(PetscFree(edata->is));
7678 PetscCall(PetscFree(edata));
7679 PetscFunctionReturn(PETSC_SUCCESS);
7680 }
7681
7682 /*@
7683 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7684 the sizes of these blocks in the matrix. An individual block may lie over several processes.
7685
7686 Collective
7687
7688 Input Parameter:
7689 . mat - the matrix
7690
7691 Level: intermediate
7692
7693 Notes:
7694 There can be zeros within the blocks
7695
7696 The blocks can overlap between processes, including laying on more than two processes
7697
7698 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7699 @*/
MatComputeVariableBlockEnvelope(Mat mat)7700 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7701 {
7702 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7703 PetscInt *diag, *odiag, sc;
7704 VecScatter scatter;
7705 PetscScalar *seqv;
7706 const PetscScalar *parv;
7707 const PetscInt *ia, *ja;
7708 PetscBool set, flag, done;
7709 Mat AA = mat, A;
7710 MPI_Comm comm;
7711 PetscMPIInt rank, size, tag;
7712 MPI_Status status;
7713 PetscContainer container;
7714 EnvelopeData *edata;
7715 Vec seq, par;
7716 IS isglobal;
7717
7718 PetscFunctionBegin;
7719 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7720 PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7721 if (!set || !flag) {
7722 /* TODO: only needs nonzero structure of transpose */
7723 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7724 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7725 }
7726 PetscCall(MatAIJGetLocalMat(AA, &A));
7727 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7728 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7729
7730 PetscCall(MatGetLocalSize(mat, &n, NULL));
7731 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7732 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7733 PetscCallMPI(MPI_Comm_size(comm, &size));
7734 PetscCallMPI(MPI_Comm_rank(comm, &rank));
7735
7736 PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7737
7738 if (rank > 0) {
7739 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7740 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7741 }
7742 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7743 for (i = 0; i < n; i++) {
7744 env = PetscMax(env, ja[ia[i + 1] - 1]);
7745 II = rstart + i;
7746 if (env == II) {
7747 starts[lblocks] = tbs;
7748 sizes[lblocks++] = 1 + II - tbs;
7749 tbs = 1 + II;
7750 }
7751 }
7752 if (rank < size - 1) {
7753 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7754 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7755 }
7756
7757 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7758 if (!set || !flag) PetscCall(MatDestroy(&AA));
7759 PetscCall(MatDestroy(&A));
7760
7761 PetscCall(PetscNew(&edata));
7762 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7763 edata->n = lblocks;
7764 /* create IS needed for extracting blocks from the original matrix */
7765 PetscCall(PetscMalloc1(lblocks, &edata->is));
7766 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7767
7768 /* Create the resulting inverse matrix nonzero structure with preallocation information */
7769 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7770 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7771 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7772 PetscCall(MatSetType(edata->C, MATAIJ));
7773
7774 /* Communicate the start and end of each row, from each block to the correct rank */
7775 /* TODO: Use PetscSF instead of VecScatter */
7776 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7777 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7778 PetscCall(VecGetArrayWrite(seq, &seqv));
7779 for (PetscInt i = 0; i < lblocks; i++) {
7780 for (PetscInt j = 0; j < sizes[i]; j++) {
7781 seqv[cnt] = starts[i];
7782 seqv[cnt + 1] = starts[i] + sizes[i];
7783 cnt += 2;
7784 }
7785 }
7786 PetscCall(VecRestoreArrayWrite(seq, &seqv));
7787 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7788 sc -= cnt;
7789 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7790 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7791 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7792 PetscCall(ISDestroy(&isglobal));
7793 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7794 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7795 PetscCall(VecScatterDestroy(&scatter));
7796 PetscCall(VecDestroy(&seq));
7797 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7798 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7799 PetscCall(VecGetArrayRead(par, &parv));
7800 cnt = 0;
7801 PetscCall(MatGetSize(mat, NULL, &n));
7802 for (PetscInt i = 0; i < mat->rmap->n; i++) {
7803 PetscInt start, end, d = 0, od = 0;
7804
7805 start = (PetscInt)PetscRealPart(parv[cnt]);
7806 end = (PetscInt)PetscRealPart(parv[cnt + 1]);
7807 cnt += 2;
7808
7809 if (start < cstart) {
7810 od += cstart - start + n - cend;
7811 d += cend - cstart;
7812 } else if (start < cend) {
7813 od += n - cend;
7814 d += cend - start;
7815 } else od += n - start;
7816 if (end <= cstart) {
7817 od -= cstart - end + n - cend;
7818 d -= cend - cstart;
7819 } else if (end < cend) {
7820 od -= n - cend;
7821 d -= cend - end;
7822 } else od -= n - end;
7823
7824 odiag[i] = od;
7825 diag[i] = d;
7826 }
7827 PetscCall(VecRestoreArrayRead(par, &parv));
7828 PetscCall(VecDestroy(&par));
7829 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7830 PetscCall(PetscFree2(diag, odiag));
7831 PetscCall(PetscFree2(sizes, starts));
7832
7833 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7834 PetscCall(PetscContainerSetPointer(container, edata));
7835 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy));
7836 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7837 PetscCall(PetscObjectDereference((PetscObject)container));
7838 PetscFunctionReturn(PETSC_SUCCESS);
7839 }
7840
7841 /*@
7842 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7843
7844 Collective
7845
7846 Input Parameters:
7847 + A - the matrix
7848 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7849
7850 Output Parameter:
7851 . C - matrix with inverted block diagonal of `A`
7852
7853 Level: advanced
7854
7855 Note:
7856 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7857
7858 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7859 @*/
MatInvertVariableBlockEnvelope(Mat A,MatReuse reuse,Mat * C)7860 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7861 {
7862 PetscContainer container;
7863 EnvelopeData *edata;
7864 PetscObjectState nonzerostate;
7865
7866 PetscFunctionBegin;
7867 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7868 if (!container) {
7869 PetscCall(MatComputeVariableBlockEnvelope(A));
7870 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7871 }
7872 PetscCall(PetscContainerGetPointer(container, &edata));
7873 PetscCall(MatGetNonzeroState(A, &nonzerostate));
7874 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7875 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7876
7877 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7878 *C = edata->C;
7879
7880 for (PetscInt i = 0; i < edata->n; i++) {
7881 Mat D;
7882 PetscScalar *dvalues;
7883
7884 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7885 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7886 PetscCall(MatSeqDenseInvert(D));
7887 PetscCall(MatDenseGetArray(D, &dvalues));
7888 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7889 PetscCall(MatDestroy(&D));
7890 }
7891 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7892 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7893 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7894 PetscFunctionReturn(PETSC_SUCCESS);
7895 }
7896
7897 /*@
7898 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7899
7900 Not Collective
7901
7902 Input Parameters:
7903 + mat - the matrix
7904 . nblocks - the number of blocks on this process, each block can only exist on a single process
7905 - bsizes - the block sizes
7906
7907 Level: intermediate
7908
7909 Notes:
7910 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7911
7912 Each variable point-block set of degrees of freedom must live on a single MPI process. That is a point block cannot straddle two MPI processes.
7913
7914 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7915 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7916 @*/
MatSetVariableBlockSizes(Mat mat,PetscInt nblocks,const PetscInt bsizes[])7917 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7918 {
7919 PetscInt ncnt = 0, nlocal;
7920
7921 PetscFunctionBegin;
7922 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7923 PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7924 PetscCheck(nblocks >= 0 && nblocks <= nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks %" PetscInt_FMT " is not in [0, %" PetscInt_FMT "]", nblocks, nlocal);
7925 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7926 PetscCheck(ncnt == nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local block sizes %" PetscInt_FMT " does not equal local size of matrix %" PetscInt_FMT, ncnt, nlocal);
7927 PetscCall(PetscFree(mat->bsizes));
7928 mat->nblocks = nblocks;
7929 PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7930 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7931 PetscFunctionReturn(PETSC_SUCCESS);
7932 }
7933
7934 /*@C
7935 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7936
7937 Not Collective; No Fortran Support
7938
7939 Input Parameter:
7940 . mat - the matrix
7941
7942 Output Parameters:
7943 + nblocks - the number of blocks on this process
7944 - bsizes - the block sizes
7945
7946 Level: intermediate
7947
7948 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7949 @*/
MatGetVariableBlockSizes(Mat mat,PetscInt * nblocks,const PetscInt * bsizes[])7950 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7951 {
7952 PetscFunctionBegin;
7953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7954 if (nblocks) *nblocks = mat->nblocks;
7955 if (bsizes) *bsizes = mat->bsizes;
7956 PetscFunctionReturn(PETSC_SUCCESS);
7957 }
7958
7959 /*@
7960 MatSelectVariableBlockSizes - When creating a submatrix, pass on the variable block sizes
7961
7962 Not Collective
7963
7964 Input Parameter:
7965 + subA - the submatrix
7966 . A - the original matrix
7967 - isrow - The `IS` of selected rows for the submatrix, must be sorted
7968
7969 Level: developer
7970
7971 Notes:
7972 If the index set is not sorted or contains off-process entries, this function will do nothing.
7973
7974 .seealso: [](ch_matrices), `Mat`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7975 @*/
MatSelectVariableBlockSizes(Mat subA,Mat A,IS isrow)7976 PetscErrorCode MatSelectVariableBlockSizes(Mat subA, Mat A, IS isrow)
7977 {
7978 const PetscInt *rows;
7979 PetscInt n, rStart, rEnd, Nb = 0;
7980 PetscBool flg = A->bsizes ? PETSC_TRUE : PETSC_FALSE;
7981
7982 PetscFunctionBegin;
7983 // The code for block size extraction does not support an unsorted IS
7984 if (flg) PetscCall(ISSorted(isrow, &flg));
7985 // We don't support originally off-diagonal blocks
7986 if (flg) {
7987 PetscCall(MatGetOwnershipRange(A, &rStart, &rEnd));
7988 PetscCall(ISGetLocalSize(isrow, &n));
7989 PetscCall(ISGetIndices(isrow, &rows));
7990 for (PetscInt i = 0; i < n && flg; ++i) {
7991 if (rows[i] < rStart || rows[i] >= rEnd) flg = PETSC_FALSE;
7992 }
7993 PetscCall(ISRestoreIndices(isrow, &rows));
7994 }
7995 // quiet return if we can't extract block size
7996 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &flg, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)subA)));
7997 if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
7998
7999 // extract block sizes
8000 PetscCall(ISGetIndices(isrow, &rows));
8001 for (PetscInt b = 0, gr = rStart, i = 0; b < A->nblocks; ++b) {
8002 PetscBool occupied = PETSC_FALSE;
8003
8004 for (PetscInt br = 0; br < A->bsizes[b]; ++br) {
8005 const PetscInt row = gr + br;
8006
8007 if (i == n) break;
8008 if (rows[i] == row) {
8009 occupied = PETSC_TRUE;
8010 ++i;
8011 }
8012 while (i < n && rows[i] < row) ++i;
8013 }
8014 gr += A->bsizes[b];
8015 if (occupied) ++Nb;
8016 }
8017 subA->nblocks = Nb;
8018 PetscCall(PetscFree(subA->bsizes));
8019 PetscCall(PetscMalloc1(subA->nblocks, &subA->bsizes));
8020 PetscInt sb = 0;
8021 for (PetscInt b = 0, gr = rStart, i = 0; b < A->nblocks; ++b) {
8022 if (sb < subA->nblocks) subA->bsizes[sb] = 0;
8023 for (PetscInt br = 0; br < A->bsizes[b]; ++br) {
8024 const PetscInt row = gr + br;
8025
8026 if (i == n) break;
8027 if (rows[i] == row) {
8028 ++subA->bsizes[sb];
8029 ++i;
8030 }
8031 while (i < n && rows[i] < row) ++i;
8032 }
8033 gr += A->bsizes[b];
8034 if (sb < subA->nblocks && subA->bsizes[sb]) ++sb;
8035 }
8036 PetscCheck(sb == subA->nblocks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of blocks %" PetscInt_FMT " != %" PetscInt_FMT, sb, subA->nblocks);
8037 PetscInt nlocal, ncnt = 0;
8038 PetscCall(MatGetLocalSize(subA, &nlocal, NULL));
8039 PetscCheck(subA->nblocks >= 0 && subA->nblocks <= nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks %" PetscInt_FMT " is not in [0, %" PetscInt_FMT "]", subA->nblocks, nlocal);
8040 for (PetscInt i = 0; i < subA->nblocks; i++) ncnt += subA->bsizes[i];
8041 PetscCheck(ncnt == nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local block sizes %" PetscInt_FMT " does not equal local size of matrix %" PetscInt_FMT, ncnt, nlocal);
8042 PetscCall(ISRestoreIndices(isrow, &rows));
8043 PetscFunctionReturn(PETSC_SUCCESS);
8044 }
8045
8046 /*@
8047 MatSetBlockSizes - Sets the matrix block row and column sizes.
8048
8049 Logically Collective
8050
8051 Input Parameters:
8052 + mat - the matrix
8053 . rbs - row block size
8054 - cbs - column block size
8055
8056 Level: intermediate
8057
8058 Notes:
8059 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
8060 If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
8061 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
8062
8063 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
8064 are compatible with the matrix local sizes.
8065
8066 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
8067
8068 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
8069 @*/
MatSetBlockSizes(Mat mat,PetscInt rbs,PetscInt cbs)8070 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
8071 {
8072 PetscFunctionBegin;
8073 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8074 PetscValidLogicalCollectiveInt(mat, rbs, 2);
8075 PetscValidLogicalCollectiveInt(mat, cbs, 3);
8076 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
8077 if (mat->rmap->refcnt) {
8078 ISLocalToGlobalMapping l2g = NULL;
8079 PetscLayout nmap = NULL;
8080
8081 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
8082 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
8083 PetscCall(PetscLayoutDestroy(&mat->rmap));
8084 mat->rmap = nmap;
8085 mat->rmap->mapping = l2g;
8086 }
8087 if (mat->cmap->refcnt) {
8088 ISLocalToGlobalMapping l2g = NULL;
8089 PetscLayout nmap = NULL;
8090
8091 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
8092 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
8093 PetscCall(PetscLayoutDestroy(&mat->cmap));
8094 mat->cmap = nmap;
8095 mat->cmap->mapping = l2g;
8096 }
8097 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
8098 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
8099 PetscFunctionReturn(PETSC_SUCCESS);
8100 }
8101
8102 /*@
8103 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
8104
8105 Logically Collective
8106
8107 Input Parameters:
8108 + mat - the matrix
8109 . fromRow - matrix from which to copy row block size
8110 - fromCol - matrix from which to copy column block size (can be same as `fromRow`)
8111
8112 Level: developer
8113
8114 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
8115 @*/
MatSetBlockSizesFromMats(Mat mat,Mat fromRow,Mat fromCol)8116 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
8117 {
8118 PetscFunctionBegin;
8119 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8120 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
8121 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
8122 PetscTryTypeMethod(mat, setblocksizes, fromRow->rmap->bs, fromCol->cmap->bs);
8123 PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
8124 PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
8125 PetscFunctionReturn(PETSC_SUCCESS);
8126 }
8127
8128 /*@
8129 MatResidual - Default routine to calculate the residual r = b - Ax
8130
8131 Collective
8132
8133 Input Parameters:
8134 + mat - the matrix
8135 . b - the right-hand-side
8136 - x - the approximate solution
8137
8138 Output Parameter:
8139 . r - location to store the residual
8140
8141 Level: developer
8142
8143 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8144 @*/
MatResidual(Mat mat,Vec b,Vec x,Vec r)8145 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8146 {
8147 PetscFunctionBegin;
8148 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8149 PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8150 PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8151 PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8152 PetscValidType(mat, 1);
8153 MatCheckPreallocated(mat, 1);
8154 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8155 if (!mat->ops->residual) {
8156 PetscCall(MatMult(mat, x, r));
8157 PetscCall(VecAYPX(r, -1.0, b));
8158 } else {
8159 PetscUseTypeMethod(mat, residual, b, x, r);
8160 }
8161 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8162 PetscFunctionReturn(PETSC_SUCCESS);
8163 }
8164
8165 /*@C
8166 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8167
8168 Collective
8169
8170 Input Parameters:
8171 + mat - the matrix
8172 . shift - 0 or 1 indicating we want the indices starting at 0 or 1
8173 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8174 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8175 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8176 always used.
8177
8178 Output Parameters:
8179 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8180 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix, use `NULL` if not needed
8181 . ja - the column indices, use `NULL` if not needed
8182 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8183 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8184
8185 Level: developer
8186
8187 Notes:
8188 You CANNOT change any of the ia[] or ja[] values.
8189
8190 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8191
8192 Fortran Notes:
8193 Use
8194 .vb
8195 PetscInt, pointer :: ia(:),ja(:)
8196 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8197 ! Access the ith and jth entries via ia(i) and ja(j)
8198 .ve
8199
8200 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8201 @*/
MatGetRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt * n,const PetscInt * ia[],const PetscInt * ja[],PetscBool * done)8202 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8203 {
8204 PetscFunctionBegin;
8205 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8206 PetscValidType(mat, 1);
8207 if (n) PetscAssertPointer(n, 5);
8208 if (ia) PetscAssertPointer(ia, 6);
8209 if (ja) PetscAssertPointer(ja, 7);
8210 if (done) PetscAssertPointer(done, 8);
8211 MatCheckPreallocated(mat, 1);
8212 if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8213 else {
8214 if (done) *done = PETSC_TRUE;
8215 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8216 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8217 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8218 }
8219 PetscFunctionReturn(PETSC_SUCCESS);
8220 }
8221
8222 /*@C
8223 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8224
8225 Collective
8226
8227 Input Parameters:
8228 + mat - the matrix
8229 . shift - 1 or zero indicating we want the indices starting at 0 or 1
8230 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8231 symmetrized
8232 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8233 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8234 always used.
8235
8236 Output Parameters:
8237 + n - number of columns in the (possibly compressed) matrix
8238 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8239 . ja - the row indices
8240 - done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8241
8242 Level: developer
8243
8244 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8245 @*/
MatGetColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt * n,const PetscInt * ia[],const PetscInt * ja[],PetscBool * done)8246 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8247 {
8248 PetscFunctionBegin;
8249 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8250 PetscValidType(mat, 1);
8251 PetscAssertPointer(n, 5);
8252 if (ia) PetscAssertPointer(ia, 6);
8253 if (ja) PetscAssertPointer(ja, 7);
8254 PetscAssertPointer(done, 8);
8255 MatCheckPreallocated(mat, 1);
8256 if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8257 else {
8258 *done = PETSC_TRUE;
8259 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8260 }
8261 PetscFunctionReturn(PETSC_SUCCESS);
8262 }
8263
8264 /*@C
8265 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8266
8267 Collective
8268
8269 Input Parameters:
8270 + mat - the matrix
8271 . shift - 1 or zero indicating we want the indices starting at 0 or 1
8272 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8273 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8274 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8275 always used.
8276 . n - size of (possibly compressed) matrix
8277 . ia - the row pointers
8278 - ja - the column indices
8279
8280 Output Parameter:
8281 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8282
8283 Level: developer
8284
8285 Note:
8286 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8287 us of the array after it has been restored. If you pass `NULL`, it will
8288 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8289
8290 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8291 @*/
MatRestoreRowIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt * n,const PetscInt * ia[],const PetscInt * ja[],PetscBool * done)8292 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8293 {
8294 PetscFunctionBegin;
8295 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8296 PetscValidType(mat, 1);
8297 if (ia) PetscAssertPointer(ia, 6);
8298 if (ja) PetscAssertPointer(ja, 7);
8299 if (done) PetscAssertPointer(done, 8);
8300 MatCheckPreallocated(mat, 1);
8301
8302 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8303 else {
8304 if (done) *done = PETSC_TRUE;
8305 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8306 if (n) *n = 0;
8307 if (ia) *ia = NULL;
8308 if (ja) *ja = NULL;
8309 }
8310 PetscFunctionReturn(PETSC_SUCCESS);
8311 }
8312
8313 /*@C
8314 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8315
8316 Collective
8317
8318 Input Parameters:
8319 + mat - the matrix
8320 . shift - 1 or zero indicating we want the indices starting at 0 or 1
8321 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8322 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8323 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8324 always used.
8325
8326 Output Parameters:
8327 + n - size of (possibly compressed) matrix
8328 . ia - the column pointers
8329 . ja - the row indices
8330 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8331
8332 Level: developer
8333
8334 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8335 @*/
MatRestoreColumnIJ(Mat mat,PetscInt shift,PetscBool symmetric,PetscBool inodecompressed,PetscInt * n,const PetscInt * ia[],const PetscInt * ja[],PetscBool * done)8336 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8337 {
8338 PetscFunctionBegin;
8339 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8340 PetscValidType(mat, 1);
8341 if (ia) PetscAssertPointer(ia, 6);
8342 if (ja) PetscAssertPointer(ja, 7);
8343 PetscAssertPointer(done, 8);
8344 MatCheckPreallocated(mat, 1);
8345
8346 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8347 else {
8348 *done = PETSC_TRUE;
8349 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8350 if (n) *n = 0;
8351 if (ia) *ia = NULL;
8352 if (ja) *ja = NULL;
8353 }
8354 PetscFunctionReturn(PETSC_SUCCESS);
8355 }
8356
8357 /*@
8358 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8359 `MatGetColumnIJ()`.
8360
8361 Collective
8362
8363 Input Parameters:
8364 + mat - the matrix
8365 . ncolors - maximum color value
8366 . n - number of entries in colorarray
8367 - colorarray - array indicating color for each column
8368
8369 Output Parameter:
8370 . iscoloring - coloring generated using colorarray information
8371
8372 Level: developer
8373
8374 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8375 @*/
MatColoringPatch(Mat mat,PetscInt ncolors,PetscInt n,ISColoringValue colorarray[],ISColoring * iscoloring)8376 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8377 {
8378 PetscFunctionBegin;
8379 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8380 PetscValidType(mat, 1);
8381 PetscAssertPointer(colorarray, 4);
8382 PetscAssertPointer(iscoloring, 5);
8383 MatCheckPreallocated(mat, 1);
8384
8385 if (!mat->ops->coloringpatch) {
8386 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8387 } else {
8388 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8389 }
8390 PetscFunctionReturn(PETSC_SUCCESS);
8391 }
8392
8393 /*@
8394 MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8395
8396 Logically Collective
8397
8398 Input Parameter:
8399 . mat - the factored matrix to be reset
8400
8401 Level: developer
8402
8403 Notes:
8404 This routine should be used only with factored matrices formed by in-place
8405 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8406 format). This option can save memory, for example, when solving nonlinear
8407 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8408 ILU(0) preconditioner.
8409
8410 One can specify in-place ILU(0) factorization by calling
8411 .vb
8412 PCType(pc,PCILU);
8413 PCFactorSeUseInPlace(pc);
8414 .ve
8415 or by using the options -pc_type ilu -pc_factor_in_place
8416
8417 In-place factorization ILU(0) can also be used as a local
8418 solver for the blocks within the block Jacobi or additive Schwarz
8419 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc
8420 for details on setting local solver options.
8421
8422 Most users should employ the `KSP` interface for linear solvers
8423 instead of working directly with matrix algebra routines such as this.
8424 See, e.g., `KSPCreate()`.
8425
8426 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8427 @*/
MatSetUnfactored(Mat mat)8428 PetscErrorCode MatSetUnfactored(Mat mat)
8429 {
8430 PetscFunctionBegin;
8431 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8432 PetscValidType(mat, 1);
8433 MatCheckPreallocated(mat, 1);
8434 mat->factortype = MAT_FACTOR_NONE;
8435 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8436 PetscUseTypeMethod(mat, setunfactored);
8437 PetscFunctionReturn(PETSC_SUCCESS);
8438 }
8439
8440 /*@
8441 MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8442 as the original matrix.
8443
8444 Collective
8445
8446 Input Parameters:
8447 + mat - the original matrix
8448 . isrow - parallel `IS` containing the rows this processor should obtain
8449 . iscol - parallel `IS` containing all columns you wish to keep. Each process should list the columns that will be in IT's "diagonal part" in the new matrix.
8450 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8451
8452 Output Parameter:
8453 . newmat - the new submatrix, of the same type as the original matrix
8454
8455 Level: advanced
8456
8457 Notes:
8458 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8459
8460 Some matrix types place restrictions on the row and column indices, such
8461 as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block;
8462 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8463
8464 The index sets may not have duplicate entries.
8465
8466 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8467 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8468 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8469 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when
8470 you are finished using it.
8471
8472 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8473 the input matrix.
8474
8475 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8476
8477 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8478 is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8479
8480 Example usage:
8481 Consider the following 8x8 matrix with 34 non-zero values, that is
8482 assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8483 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8484 as follows
8485 .vb
8486 1 2 0 | 0 3 0 | 0 4
8487 Proc0 0 5 6 | 7 0 0 | 8 0
8488 9 0 10 | 11 0 0 | 12 0
8489 -------------------------------------
8490 13 0 14 | 15 16 17 | 0 0
8491 Proc1 0 18 0 | 19 20 21 | 0 0
8492 0 0 0 | 22 23 0 | 24 0
8493 -------------------------------------
8494 Proc2 25 26 27 | 0 0 28 | 29 0
8495 30 0 0 | 31 32 33 | 0 34
8496 .ve
8497
8498 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is
8499
8500 .vb
8501 2 0 | 0 3 0 | 0
8502 Proc0 5 6 | 7 0 0 | 8
8503 -------------------------------
8504 Proc1 18 0 | 19 20 21 | 0
8505 -------------------------------
8506 Proc2 26 27 | 0 0 28 | 29
8507 0 0 | 31 32 33 | 0
8508 .ve
8509
8510 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8511 @*/
MatCreateSubMatrix(Mat mat,IS isrow,IS iscol,MatReuse cll,Mat * newmat)8512 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8513 {
8514 PetscMPIInt size;
8515 Mat *local;
8516 IS iscoltmp;
8517 PetscBool flg;
8518
8519 PetscFunctionBegin;
8520 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8521 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8522 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8523 PetscAssertPointer(newmat, 5);
8524 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8525 PetscValidType(mat, 1);
8526 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8527 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8528 PetscCheck(cll != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_INPLACE_MATRIX");
8529
8530 MatCheckPreallocated(mat, 1);
8531 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8532
8533 if (!iscol || isrow == iscol) {
8534 PetscBool stride;
8535 PetscMPIInt grabentirematrix = 0, grab;
8536 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8537 if (stride) {
8538 PetscInt first, step, n, rstart, rend;
8539 PetscCall(ISStrideGetInfo(isrow, &first, &step));
8540 if (step == 1) {
8541 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8542 if (rstart == first) {
8543 PetscCall(ISGetLocalSize(isrow, &n));
8544 if (n == rend - rstart) grabentirematrix = 1;
8545 }
8546 }
8547 }
8548 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8549 if (grab) {
8550 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8551 if (cll == MAT_INITIAL_MATRIX) {
8552 *newmat = mat;
8553 PetscCall(PetscObjectReference((PetscObject)mat));
8554 }
8555 PetscFunctionReturn(PETSC_SUCCESS);
8556 }
8557 }
8558
8559 if (!iscol) {
8560 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8561 } else {
8562 iscoltmp = iscol;
8563 }
8564
8565 /* if original matrix is on just one processor then use submatrix generated */
8566 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8567 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8568 goto setproperties;
8569 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8570 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8571 *newmat = *local;
8572 PetscCall(PetscFree(local));
8573 goto setproperties;
8574 } else if (!mat->ops->createsubmatrix) {
8575 /* Create a new matrix type that implements the operation using the full matrix */
8576 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8577 switch (cll) {
8578 case MAT_INITIAL_MATRIX:
8579 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8580 break;
8581 case MAT_REUSE_MATRIX:
8582 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8583 break;
8584 default:
8585 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8586 }
8587 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8588 goto setproperties;
8589 }
8590
8591 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8592 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8593 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8594
8595 setproperties:
8596 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8597 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8598 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8599 }
8600 if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8601 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8602 if (!iscol || isrow == iscol) PetscCall(MatSelectVariableBlockSizes(*newmat, mat, isrow));
8603 PetscFunctionReturn(PETSC_SUCCESS);
8604 }
8605
8606 /*@
8607 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8608
8609 Not Collective
8610
8611 Input Parameters:
8612 + A - the matrix we wish to propagate options from
8613 - B - the matrix we wish to propagate options to
8614
8615 Level: beginner
8616
8617 Note:
8618 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8619
8620 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8621 @*/
MatPropagateSymmetryOptions(Mat A,Mat B)8622 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8623 {
8624 PetscFunctionBegin;
8625 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8626 PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8627 B->symmetry_eternal = A->symmetry_eternal;
8628 B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8629 B->symmetric = A->symmetric;
8630 B->structurally_symmetric = A->structurally_symmetric;
8631 B->spd = A->spd;
8632 B->hermitian = A->hermitian;
8633 PetscFunctionReturn(PETSC_SUCCESS);
8634 }
8635
8636 /*@
8637 MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8638 used during the assembly process to store values that belong to
8639 other processors.
8640
8641 Not Collective
8642
8643 Input Parameters:
8644 + mat - the matrix
8645 . size - the initial size of the stash.
8646 - bsize - the initial size of the block-stash(if used).
8647
8648 Options Database Keys:
8649 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size
8650 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size
8651
8652 Level: intermediate
8653
8654 Notes:
8655 The block-stash is used for values set with `MatSetValuesBlocked()` while
8656 the stash is used for values set with `MatSetValues()`
8657
8658 Run with the option -info and look for output of the form
8659 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8660 to determine the appropriate value, MM, to use for size and
8661 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8662 to determine the value, BMM to use for bsize
8663
8664 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8665 @*/
MatStashSetInitialSize(Mat mat,PetscInt size,PetscInt bsize)8666 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8667 {
8668 PetscFunctionBegin;
8669 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8670 PetscValidType(mat, 1);
8671 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8672 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8673 PetscFunctionReturn(PETSC_SUCCESS);
8674 }
8675
8676 /*@
8677 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8678 the matrix
8679
8680 Neighbor-wise Collective
8681
8682 Input Parameters:
8683 + A - the matrix
8684 . x - the vector to be multiplied by the interpolation operator
8685 - y - the vector to be added to the result
8686
8687 Output Parameter:
8688 . w - the resulting vector
8689
8690 Level: intermediate
8691
8692 Notes:
8693 `w` may be the same vector as `y`.
8694
8695 This allows one to use either the restriction or interpolation (its transpose)
8696 matrix to do the interpolation
8697
8698 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8699 @*/
MatInterpolateAdd(Mat A,Vec x,Vec y,Vec w)8700 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8701 {
8702 PetscInt M, N, Ny;
8703
8704 PetscFunctionBegin;
8705 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8706 PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8707 PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8708 PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8709 PetscCall(MatGetSize(A, &M, &N));
8710 PetscCall(VecGetSize(y, &Ny));
8711 if (M == Ny) {
8712 PetscCall(MatMultAdd(A, x, y, w));
8713 } else {
8714 PetscCall(MatMultTransposeAdd(A, x, y, w));
8715 }
8716 PetscFunctionReturn(PETSC_SUCCESS);
8717 }
8718
8719 /*@
8720 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8721 the matrix
8722
8723 Neighbor-wise Collective
8724
8725 Input Parameters:
8726 + A - the matrix
8727 - x - the vector to be interpolated
8728
8729 Output Parameter:
8730 . y - the resulting vector
8731
8732 Level: intermediate
8733
8734 Note:
8735 This allows one to use either the restriction or interpolation (its transpose)
8736 matrix to do the interpolation
8737
8738 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8739 @*/
MatInterpolate(Mat A,Vec x,Vec y)8740 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8741 {
8742 PetscInt M, N, Ny;
8743
8744 PetscFunctionBegin;
8745 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8746 PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8747 PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8748 PetscCall(MatGetSize(A, &M, &N));
8749 PetscCall(VecGetSize(y, &Ny));
8750 if (M == Ny) {
8751 PetscCall(MatMult(A, x, y));
8752 } else {
8753 PetscCall(MatMultTranspose(A, x, y));
8754 }
8755 PetscFunctionReturn(PETSC_SUCCESS);
8756 }
8757
8758 /*@
8759 MatRestrict - $y = A*x$ or $A^T*x$
8760
8761 Neighbor-wise Collective
8762
8763 Input Parameters:
8764 + A - the matrix
8765 - x - the vector to be restricted
8766
8767 Output Parameter:
8768 . y - the resulting vector
8769
8770 Level: intermediate
8771
8772 Note:
8773 This allows one to use either the restriction or interpolation (its transpose)
8774 matrix to do the restriction
8775
8776 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8777 @*/
MatRestrict(Mat A,Vec x,Vec y)8778 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8779 {
8780 PetscInt M, N, Nx;
8781
8782 PetscFunctionBegin;
8783 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8784 PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8785 PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8786 PetscCall(MatGetSize(A, &M, &N));
8787 PetscCall(VecGetSize(x, &Nx));
8788 if (M == Nx) {
8789 PetscCall(MatMultTranspose(A, x, y));
8790 } else {
8791 PetscCall(MatMult(A, x, y));
8792 }
8793 PetscFunctionReturn(PETSC_SUCCESS);
8794 }
8795
8796 /*@
8797 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8798
8799 Neighbor-wise Collective
8800
8801 Input Parameters:
8802 + A - the matrix
8803 . x - the input dense matrix to be multiplied
8804 - w - the input dense matrix to be added to the result
8805
8806 Output Parameter:
8807 . y - the output dense matrix
8808
8809 Level: intermediate
8810
8811 Note:
8812 This allows one to use either the restriction or interpolation (its transpose)
8813 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8814 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8815
8816 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8817 @*/
MatMatInterpolateAdd(Mat A,Mat x,Mat w,Mat * y)8818 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8819 {
8820 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8821 PetscBool trans = PETSC_TRUE;
8822 MatReuse reuse = MAT_INITIAL_MATRIX;
8823
8824 PetscFunctionBegin;
8825 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8826 PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8827 PetscValidType(x, 2);
8828 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8829 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8830 PetscCall(MatGetSize(A, &M, &N));
8831 PetscCall(MatGetSize(x, &Mx, &Nx));
8832 if (N == Mx) trans = PETSC_FALSE;
8833 else PetscCheck(M == Mx, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Size mismatch: A %" PetscInt_FMT "x%" PetscInt_FMT ", X %" PetscInt_FMT "x%" PetscInt_FMT, M, N, Mx, Nx);
8834 Mo = trans ? N : M;
8835 if (*y) {
8836 PetscCall(MatGetSize(*y, &My, &Ny));
8837 if (Mo == My && Nx == Ny) {
8838 reuse = MAT_REUSE_MATRIX;
8839 } else {
8840 PetscCheck(w || *y != w, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot reuse y and w, size mismatch: A %" PetscInt_FMT "x%" PetscInt_FMT ", X %" PetscInt_FMT "x%" PetscInt_FMT ", Y %" PetscInt_FMT "x%" PetscInt_FMT, M, N, Mx, Nx, My, Ny);
8841 PetscCall(MatDestroy(y));
8842 }
8843 }
8844
8845 if (w && *y == w) { /* this is to minimize changes in PCMG */
8846 PetscBool flg;
8847
8848 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8849 if (w) {
8850 PetscInt My, Ny, Mw, Nw;
8851
8852 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8853 PetscCall(MatGetSize(*y, &My, &Ny));
8854 PetscCall(MatGetSize(w, &Mw, &Nw));
8855 if (!flg || My != Mw || Ny != Nw) w = NULL;
8856 }
8857 if (!w) {
8858 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8859 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8860 PetscCall(PetscObjectDereference((PetscObject)w));
8861 } else {
8862 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8863 }
8864 }
8865 if (!trans) {
8866 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8867 } else {
8868 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8869 }
8870 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8871 PetscFunctionReturn(PETSC_SUCCESS);
8872 }
8873
8874 /*@
8875 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8876
8877 Neighbor-wise Collective
8878
8879 Input Parameters:
8880 + A - the matrix
8881 - x - the input dense matrix
8882
8883 Output Parameter:
8884 . y - the output dense matrix
8885
8886 Level: intermediate
8887
8888 Note:
8889 This allows one to use either the restriction or interpolation (its transpose)
8890 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8891 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8892
8893 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8894 @*/
MatMatInterpolate(Mat A,Mat x,Mat * y)8895 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8896 {
8897 PetscFunctionBegin;
8898 PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8899 PetscFunctionReturn(PETSC_SUCCESS);
8900 }
8901
8902 /*@
8903 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8904
8905 Neighbor-wise Collective
8906
8907 Input Parameters:
8908 + A - the matrix
8909 - x - the input dense matrix
8910
8911 Output Parameter:
8912 . y - the output dense matrix
8913
8914 Level: intermediate
8915
8916 Note:
8917 This allows one to use either the restriction or interpolation (its transpose)
8918 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8919 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8920
8921 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8922 @*/
MatMatRestrict(Mat A,Mat x,Mat * y)8923 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8924 {
8925 PetscFunctionBegin;
8926 PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8927 PetscFunctionReturn(PETSC_SUCCESS);
8928 }
8929
8930 /*@
8931 MatGetNullSpace - retrieves the null space of a matrix.
8932
8933 Logically Collective
8934
8935 Input Parameters:
8936 + mat - the matrix
8937 - nullsp - the null space object
8938
8939 Level: developer
8940
8941 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8942 @*/
MatGetNullSpace(Mat mat,MatNullSpace * nullsp)8943 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8944 {
8945 PetscFunctionBegin;
8946 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8947 PetscAssertPointer(nullsp, 2);
8948 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8949 PetscFunctionReturn(PETSC_SUCCESS);
8950 }
8951
8952 /*@C
8953 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8954
8955 Logically Collective
8956
8957 Input Parameters:
8958 + n - the number of matrices
8959 - mat - the array of matrices
8960
8961 Output Parameters:
8962 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
8963
8964 Level: developer
8965
8966 Note:
8967 Call `MatRestoreNullspaces()` to provide these to another array of matrices
8968
8969 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8970 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
8971 @*/
MatGetNullSpaces(PetscInt n,Mat mat[],MatNullSpace * nullsp[])8972 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8973 {
8974 PetscFunctionBegin;
8975 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8976 PetscAssertPointer(mat, 2);
8977 PetscAssertPointer(nullsp, 3);
8978
8979 PetscCall(PetscCalloc1(3 * n, nullsp));
8980 for (PetscInt i = 0; i < n; i++) {
8981 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8982 (*nullsp)[i] = mat[i]->nullsp;
8983 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
8984 (*nullsp)[n + i] = mat[i]->nearnullsp;
8985 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
8986 (*nullsp)[2 * n + i] = mat[i]->transnullsp;
8987 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
8988 }
8989 PetscFunctionReturn(PETSC_SUCCESS);
8990 }
8991
8992 /*@C
8993 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
8994
8995 Logically Collective
8996
8997 Input Parameters:
8998 + n - the number of matrices
8999 . mat - the array of matrices
9000 - nullsp - an array of null spaces
9001
9002 Level: developer
9003
9004 Note:
9005 Call `MatGetNullSpaces()` to create `nullsp`
9006
9007 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9008 `MatNullSpaceRemove()`, `MatGetNullSpaces()`
9009 @*/
MatRestoreNullSpaces(PetscInt n,Mat mat[],MatNullSpace * nullsp[])9010 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9011 {
9012 PetscFunctionBegin;
9013 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9014 PetscAssertPointer(mat, 2);
9015 PetscAssertPointer(nullsp, 3);
9016 PetscAssertPointer(*nullsp, 3);
9017
9018 for (PetscInt i = 0; i < n; i++) {
9019 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9020 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
9021 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
9022 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
9023 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
9024 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
9025 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
9026 }
9027 PetscCall(PetscFree(*nullsp));
9028 PetscFunctionReturn(PETSC_SUCCESS);
9029 }
9030
9031 /*@
9032 MatSetNullSpace - attaches a null space to a matrix.
9033
9034 Logically Collective
9035
9036 Input Parameters:
9037 + mat - the matrix
9038 - nullsp - the null space object
9039
9040 Level: advanced
9041
9042 Notes:
9043 This null space is used by the `KSP` linear solvers to solve singular systems.
9044
9045 Overwrites any previous null space that may have been attached. You can remove the null space from the matrix object by calling this routine with an nullsp of `NULL`
9046
9047 For inconsistent singular systems (linear systems where the right-hand side is not in the range of the operator) the `KSP` residuals will not converge
9048 to zero but the linear system will still be solved in a least squares sense.
9049
9050 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
9051 the domain of a matrix $A$ (from $R^n$ to $R^m$ ($m$ rows, $n$ columns) $R^n$ = the direct sum of the null space of $A$, $n(A)$, plus the range of $A^T$, $R(A^T)$.
9052 Similarly $R^m$ = direct sum $n(A^T) + R(A)$. Hence the linear system $A x = b$ has a solution only if $b$ in $R(A)$ (or correspondingly $b$ is orthogonal to
9053 $n(A^T))$ and if $x$ is a solution then $x + \alpha n(A)$ is a solution for any $\alpha$. The minimum norm solution is orthogonal to $n(A)$. For problems without a solution
9054 the solution that minimizes the norm of the residual (the least squares solution) can be obtained by solving $A x = \hat{b}$ where $\hat{b}$ is $b$ orthogonalized to the $n(A^T)$.
9055 This $\hat{b}$ can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
9056
9057 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one has called
9058 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
9059 routine also automatically calls `MatSetTransposeNullSpace()`.
9060
9061 The user should call `MatNullSpaceDestroy()`.
9062
9063 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
9064 `KSPSetPCSide()`
9065 @*/
MatSetNullSpace(Mat mat,MatNullSpace nullsp)9066 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
9067 {
9068 PetscFunctionBegin;
9069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9070 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9071 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9072 PetscCall(MatNullSpaceDestroy(&mat->nullsp));
9073 mat->nullsp = nullsp;
9074 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
9075 PetscFunctionReturn(PETSC_SUCCESS);
9076 }
9077
9078 /*@
9079 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
9080
9081 Logically Collective
9082
9083 Input Parameters:
9084 + mat - the matrix
9085 - nullsp - the null space object
9086
9087 Level: developer
9088
9089 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
9090 @*/
MatGetTransposeNullSpace(Mat mat,MatNullSpace * nullsp)9091 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
9092 {
9093 PetscFunctionBegin;
9094 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9095 PetscValidType(mat, 1);
9096 PetscAssertPointer(nullsp, 2);
9097 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
9098 PetscFunctionReturn(PETSC_SUCCESS);
9099 }
9100
9101 /*@
9102 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
9103
9104 Logically Collective
9105
9106 Input Parameters:
9107 + mat - the matrix
9108 - nullsp - the null space object
9109
9110 Level: advanced
9111
9112 Notes:
9113 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9114
9115 See `MatSetNullSpace()`
9116
9117 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9118 @*/
MatSetTransposeNullSpace(Mat mat,MatNullSpace nullsp)9119 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9120 {
9121 PetscFunctionBegin;
9122 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9123 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9124 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9125 PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9126 mat->transnullsp = nullsp;
9127 PetscFunctionReturn(PETSC_SUCCESS);
9128 }
9129
9130 /*@
9131 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9132 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9133
9134 Logically Collective
9135
9136 Input Parameters:
9137 + mat - the matrix
9138 - nullsp - the null space object
9139
9140 Level: advanced
9141
9142 Notes:
9143 Overwrites any previous near null space that may have been attached
9144
9145 You can remove the null space by calling this routine with an `nullsp` of `NULL`
9146
9147 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9148 @*/
MatSetNearNullSpace(Mat mat,MatNullSpace nullsp)9149 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9150 {
9151 PetscFunctionBegin;
9152 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9153 PetscValidType(mat, 1);
9154 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9155 MatCheckPreallocated(mat, 1);
9156 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9157 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9158 mat->nearnullsp = nullsp;
9159 PetscFunctionReturn(PETSC_SUCCESS);
9160 }
9161
9162 /*@
9163 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9164
9165 Not Collective
9166
9167 Input Parameter:
9168 . mat - the matrix
9169
9170 Output Parameter:
9171 . nullsp - the null space object, `NULL` if not set
9172
9173 Level: advanced
9174
9175 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9176 @*/
MatGetNearNullSpace(Mat mat,MatNullSpace * nullsp)9177 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9178 {
9179 PetscFunctionBegin;
9180 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9181 PetscValidType(mat, 1);
9182 PetscAssertPointer(nullsp, 2);
9183 MatCheckPreallocated(mat, 1);
9184 *nullsp = mat->nearnullsp;
9185 PetscFunctionReturn(PETSC_SUCCESS);
9186 }
9187
9188 /*@
9189 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9190
9191 Collective
9192
9193 Input Parameters:
9194 + mat - the matrix
9195 . row - row/column permutation
9196 - info - information on desired factorization process
9197
9198 Level: developer
9199
9200 Notes:
9201 Probably really in-place only when level of fill is zero, otherwise allocates
9202 new space to store factored matrix and deletes previous memory.
9203
9204 Most users should employ the `KSP` interface for linear solvers
9205 instead of working directly with matrix algebra routines such as this.
9206 See, e.g., `KSPCreate()`.
9207
9208 Fortran Note:
9209 A valid (non-null) `info` argument must be provided
9210
9211 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9212 @*/
MatICCFactor(Mat mat,IS row,const MatFactorInfo * info)9213 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9214 {
9215 PetscFunctionBegin;
9216 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9217 PetscValidType(mat, 1);
9218 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9219 PetscAssertPointer(info, 3);
9220 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9221 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9222 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9223 MatCheckPreallocated(mat, 1);
9224 PetscUseTypeMethod(mat, iccfactor, row, info);
9225 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9226 PetscFunctionReturn(PETSC_SUCCESS);
9227 }
9228
9229 /*@
9230 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9231 ghosted ones.
9232
9233 Not Collective
9234
9235 Input Parameters:
9236 + mat - the matrix
9237 - diag - the diagonal values, including ghost ones
9238
9239 Level: developer
9240
9241 Notes:
9242 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9243
9244 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9245
9246 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9247 @*/
MatDiagonalScaleLocal(Mat mat,Vec diag)9248 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9249 {
9250 PetscMPIInt size;
9251
9252 PetscFunctionBegin;
9253 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9254 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9255 PetscValidType(mat, 1);
9256
9257 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9258 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9259 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9260 if (size == 1) {
9261 PetscInt n, m;
9262 PetscCall(VecGetSize(diag, &n));
9263 PetscCall(MatGetSize(mat, NULL, &m));
9264 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9265 PetscCall(MatDiagonalScale(mat, NULL, diag));
9266 } else {
9267 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9268 }
9269 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9270 PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9271 PetscFunctionReturn(PETSC_SUCCESS);
9272 }
9273
9274 /*@
9275 MatGetInertia - Gets the inertia from a factored matrix
9276
9277 Collective
9278
9279 Input Parameter:
9280 . mat - the matrix
9281
9282 Output Parameters:
9283 + nneg - number of negative eigenvalues
9284 . nzero - number of zero eigenvalues
9285 - npos - number of positive eigenvalues
9286
9287 Level: advanced
9288
9289 Note:
9290 Matrix must have been factored by `MatCholeskyFactor()`
9291
9292 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9293 @*/
MatGetInertia(Mat mat,PetscInt * nneg,PetscInt * nzero,PetscInt * npos)9294 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9295 {
9296 PetscFunctionBegin;
9297 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9298 PetscValidType(mat, 1);
9299 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9300 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9301 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9302 PetscFunctionReturn(PETSC_SUCCESS);
9303 }
9304
9305 /*@C
9306 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9307
9308 Neighbor-wise Collective
9309
9310 Input Parameters:
9311 + mat - the factored matrix obtained with `MatGetFactor()`
9312 - b - the right-hand-side vectors
9313
9314 Output Parameter:
9315 . x - the result vectors
9316
9317 Level: developer
9318
9319 Note:
9320 The vectors `b` and `x` cannot be the same. I.e., one cannot
9321 call `MatSolves`(A,x,x).
9322
9323 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9324 @*/
MatSolves(Mat mat,Vecs b,Vecs x)9325 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9326 {
9327 PetscFunctionBegin;
9328 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9329 PetscValidType(mat, 1);
9330 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9331 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9332 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9333
9334 MatCheckPreallocated(mat, 1);
9335 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9336 PetscUseTypeMethod(mat, solves, b, x);
9337 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9338 PetscFunctionReturn(PETSC_SUCCESS);
9339 }
9340
9341 /*@
9342 MatIsSymmetric - Test whether a matrix is symmetric
9343
9344 Collective
9345
9346 Input Parameters:
9347 + A - the matrix to test
9348 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9349
9350 Output Parameter:
9351 . flg - the result
9352
9353 Level: intermediate
9354
9355 Notes:
9356 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9357
9358 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9359
9360 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9361 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9362
9363 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9364 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9365 @*/
MatIsSymmetric(Mat A,PetscReal tol,PetscBool * flg)9366 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9367 {
9368 PetscFunctionBegin;
9369 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9370 PetscAssertPointer(flg, 3);
9371 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric);
9372 else {
9373 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9374 else PetscCall(MatIsTranspose(A, A, tol, flg));
9375 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9376 }
9377 PetscFunctionReturn(PETSC_SUCCESS);
9378 }
9379
9380 /*@
9381 MatIsHermitian - Test whether a matrix is Hermitian
9382
9383 Collective
9384
9385 Input Parameters:
9386 + A - the matrix to test
9387 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9388
9389 Output Parameter:
9390 . flg - the result
9391
9392 Level: intermediate
9393
9394 Notes:
9395 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9396
9397 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9398
9399 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9400 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9401
9402 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9403 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9404 @*/
MatIsHermitian(Mat A,PetscReal tol,PetscBool * flg)9405 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9406 {
9407 PetscFunctionBegin;
9408 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9409 PetscAssertPointer(flg, 3);
9410 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian);
9411 else {
9412 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9413 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9414 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9415 }
9416 PetscFunctionReturn(PETSC_SUCCESS);
9417 }
9418
9419 /*@
9420 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9421
9422 Not Collective
9423
9424 Input Parameter:
9425 . A - the matrix to check
9426
9427 Output Parameters:
9428 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9429 - flg - the result (only valid if set is `PETSC_TRUE`)
9430
9431 Level: advanced
9432
9433 Notes:
9434 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9435 if you want it explicitly checked
9436
9437 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9438 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9439
9440 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9441 @*/
MatIsSymmetricKnown(Mat A,PetscBool * set,PetscBool * flg)9442 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9443 {
9444 PetscFunctionBegin;
9445 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9446 PetscAssertPointer(set, 2);
9447 PetscAssertPointer(flg, 3);
9448 if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9449 *set = PETSC_TRUE;
9450 *flg = PetscBool3ToBool(A->symmetric);
9451 } else {
9452 *set = PETSC_FALSE;
9453 }
9454 PetscFunctionReturn(PETSC_SUCCESS);
9455 }
9456
9457 /*@
9458 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9459
9460 Not Collective
9461
9462 Input Parameter:
9463 . A - the matrix to check
9464
9465 Output Parameters:
9466 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9467 - flg - the result (only valid if set is `PETSC_TRUE`)
9468
9469 Level: advanced
9470
9471 Notes:
9472 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9473
9474 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9475 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9476
9477 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9478 @*/
MatIsSPDKnown(Mat A,PetscBool * set,PetscBool * flg)9479 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9480 {
9481 PetscFunctionBegin;
9482 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9483 PetscAssertPointer(set, 2);
9484 PetscAssertPointer(flg, 3);
9485 if (A->spd != PETSC_BOOL3_UNKNOWN) {
9486 *set = PETSC_TRUE;
9487 *flg = PetscBool3ToBool(A->spd);
9488 } else {
9489 *set = PETSC_FALSE;
9490 }
9491 PetscFunctionReturn(PETSC_SUCCESS);
9492 }
9493
9494 /*@
9495 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9496
9497 Not Collective
9498
9499 Input Parameter:
9500 . A - the matrix to check
9501
9502 Output Parameters:
9503 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9504 - flg - the result (only valid if set is `PETSC_TRUE`)
9505
9506 Level: advanced
9507
9508 Notes:
9509 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9510 if you want it explicitly checked
9511
9512 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9513 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9514
9515 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9516 @*/
MatIsHermitianKnown(Mat A,PetscBool * set,PetscBool * flg)9517 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9518 {
9519 PetscFunctionBegin;
9520 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9521 PetscAssertPointer(set, 2);
9522 PetscAssertPointer(flg, 3);
9523 if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9524 *set = PETSC_TRUE;
9525 *flg = PetscBool3ToBool(A->hermitian);
9526 } else {
9527 *set = PETSC_FALSE;
9528 }
9529 PetscFunctionReturn(PETSC_SUCCESS);
9530 }
9531
9532 /*@
9533 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9534
9535 Collective
9536
9537 Input Parameter:
9538 . A - the matrix to test
9539
9540 Output Parameter:
9541 . flg - the result
9542
9543 Level: intermediate
9544
9545 Notes:
9546 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9547
9548 One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9549 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9550
9551 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9552 @*/
MatIsStructurallySymmetric(Mat A,PetscBool * flg)9553 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9554 {
9555 PetscFunctionBegin;
9556 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9557 PetscAssertPointer(flg, 2);
9558 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9559 *flg = PetscBool3ToBool(A->structurally_symmetric);
9560 } else {
9561 PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9562 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9563 }
9564 PetscFunctionReturn(PETSC_SUCCESS);
9565 }
9566
9567 /*@
9568 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9569
9570 Not Collective
9571
9572 Input Parameter:
9573 . A - the matrix to check
9574
9575 Output Parameters:
9576 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9577 - flg - the result (only valid if set is PETSC_TRUE)
9578
9579 Level: advanced
9580
9581 Notes:
9582 One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9583 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9584
9585 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9586
9587 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9588 @*/
MatIsStructurallySymmetricKnown(Mat A,PetscBool * set,PetscBool * flg)9589 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9590 {
9591 PetscFunctionBegin;
9592 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9593 PetscAssertPointer(set, 2);
9594 PetscAssertPointer(flg, 3);
9595 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9596 *set = PETSC_TRUE;
9597 *flg = PetscBool3ToBool(A->structurally_symmetric);
9598 } else {
9599 *set = PETSC_FALSE;
9600 }
9601 PetscFunctionReturn(PETSC_SUCCESS);
9602 }
9603
9604 /*@
9605 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9606 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9607
9608 Not Collective
9609
9610 Input Parameter:
9611 . mat - the matrix
9612
9613 Output Parameters:
9614 + nstash - the size of the stash
9615 . reallocs - the number of additional mallocs incurred.
9616 . bnstash - the size of the block stash
9617 - breallocs - the number of additional mallocs incurred.in the block stash
9618
9619 Level: advanced
9620
9621 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9622 @*/
MatStashGetInfo(Mat mat,PetscInt * nstash,PetscInt * reallocs,PetscInt * bnstash,PetscInt * breallocs)9623 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9624 {
9625 PetscFunctionBegin;
9626 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9627 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9628 PetscFunctionReturn(PETSC_SUCCESS);
9629 }
9630
9631 /*@
9632 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9633 parallel layout, `PetscLayout` for rows and columns
9634
9635 Collective
9636
9637 Input Parameter:
9638 . mat - the matrix
9639
9640 Output Parameters:
9641 + right - (optional) vector that the matrix can be multiplied against
9642 - left - (optional) vector that the matrix vector product can be stored in
9643
9644 Level: advanced
9645
9646 Notes:
9647 The blocksize of the returned vectors is determined by the row and column block sizes set with `MatSetBlockSizes()` or the single blocksize (same for both) set by `MatSetBlockSize()`.
9648
9649 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9650
9651 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9652 @*/
MatCreateVecs(Mat mat,Vec * right,Vec * left)9653 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9654 {
9655 PetscFunctionBegin;
9656 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9657 PetscValidType(mat, 1);
9658 if (mat->ops->getvecs) {
9659 PetscUseTypeMethod(mat, getvecs, right, left);
9660 } else {
9661 if (right) {
9662 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9663 PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9664 PetscCall(VecSetType(*right, mat->defaultvectype));
9665 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9666 if (mat->boundtocpu && mat->bindingpropagates) {
9667 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9668 PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9669 }
9670 #endif
9671 }
9672 if (left) {
9673 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9674 PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9675 PetscCall(VecSetType(*left, mat->defaultvectype));
9676 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9677 if (mat->boundtocpu && mat->bindingpropagates) {
9678 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9679 PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9680 }
9681 #endif
9682 }
9683 }
9684 PetscFunctionReturn(PETSC_SUCCESS);
9685 }
9686
9687 /*@
9688 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9689 with default values.
9690
9691 Not Collective
9692
9693 Input Parameter:
9694 . info - the `MatFactorInfo` data structure
9695
9696 Level: developer
9697
9698 Notes:
9699 The solvers are generally used through the `KSP` and `PC` objects, for example
9700 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9701
9702 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9703
9704 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9705 @*/
MatFactorInfoInitialize(MatFactorInfo * info)9706 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9707 {
9708 PetscFunctionBegin;
9709 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9710 PetscFunctionReturn(PETSC_SUCCESS);
9711 }
9712
9713 /*@
9714 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9715
9716 Collective
9717
9718 Input Parameters:
9719 + mat - the factored matrix
9720 - is - the index set defining the Schur indices (0-based)
9721
9722 Level: advanced
9723
9724 Notes:
9725 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9726
9727 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9728
9729 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9730
9731 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9732 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9733 @*/
MatFactorSetSchurIS(Mat mat,IS is)9734 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9735 {
9736 PetscErrorCode (*f)(Mat, IS);
9737
9738 PetscFunctionBegin;
9739 PetscValidType(mat, 1);
9740 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9741 PetscValidType(is, 2);
9742 PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9743 PetscCheckSameComm(mat, 1, is, 2);
9744 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9745 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9746 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9747 PetscCall(MatDestroy(&mat->schur));
9748 PetscCall((*f)(mat, is));
9749 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9750 PetscFunctionReturn(PETSC_SUCCESS);
9751 }
9752
9753 /*@
9754 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9755
9756 Logically Collective
9757
9758 Input Parameters:
9759 + F - the factored matrix obtained by calling `MatGetFactor()`
9760 . S - location where to return the Schur complement, can be `NULL`
9761 - status - the status of the Schur complement matrix, can be `NULL`
9762
9763 Level: advanced
9764
9765 Notes:
9766 You must call `MatFactorSetSchurIS()` before calling this routine.
9767
9768 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9769
9770 The routine provides a copy of the Schur matrix stored within the solver data structures.
9771 The caller must destroy the object when it is no longer needed.
9772 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9773
9774 Use `MatFactorGetSchurComplement()` to get access to the Schur complement matrix inside the factored matrix instead of making a copy of it (which this function does)
9775
9776 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9777
9778 Developer Note:
9779 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9780 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9781
9782 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9783 @*/
MatFactorCreateSchurComplement(Mat F,Mat * S,MatFactorSchurStatus * status)9784 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9785 {
9786 PetscFunctionBegin;
9787 PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9788 if (S) PetscAssertPointer(S, 2);
9789 if (status) PetscAssertPointer(status, 3);
9790 if (S) {
9791 PetscErrorCode (*f)(Mat, Mat *);
9792
9793 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9794 if (f) {
9795 PetscCall((*f)(F, S));
9796 } else {
9797 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9798 }
9799 }
9800 if (status) *status = F->schur_status;
9801 PetscFunctionReturn(PETSC_SUCCESS);
9802 }
9803
9804 /*@
9805 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9806
9807 Logically Collective
9808
9809 Input Parameters:
9810 + F - the factored matrix obtained by calling `MatGetFactor()`
9811 . S - location where to return the Schur complement, can be `NULL`
9812 - status - the status of the Schur complement matrix, can be `NULL`
9813
9814 Level: advanced
9815
9816 Notes:
9817 You must call `MatFactorSetSchurIS()` before calling this routine.
9818
9819 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9820
9821 The routine returns a the Schur Complement stored within the data structures of the solver.
9822
9823 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9824
9825 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9826
9827 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9828
9829 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9830
9831 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9832 @*/
MatFactorGetSchurComplement(Mat F,Mat * S,MatFactorSchurStatus * status)9833 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9834 {
9835 PetscFunctionBegin;
9836 PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9837 if (S) {
9838 PetscAssertPointer(S, 2);
9839 *S = F->schur;
9840 }
9841 if (status) {
9842 PetscAssertPointer(status, 3);
9843 *status = F->schur_status;
9844 }
9845 PetscFunctionReturn(PETSC_SUCCESS);
9846 }
9847
MatFactorUpdateSchurStatus_Private(Mat F)9848 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9849 {
9850 Mat S = F->schur;
9851
9852 PetscFunctionBegin;
9853 switch (F->schur_status) {
9854 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9855 case MAT_FACTOR_SCHUR_INVERTED:
9856 if (S) {
9857 S->ops->solve = NULL;
9858 S->ops->matsolve = NULL;
9859 S->ops->solvetranspose = NULL;
9860 S->ops->matsolvetranspose = NULL;
9861 S->ops->solveadd = NULL;
9862 S->ops->solvetransposeadd = NULL;
9863 S->factortype = MAT_FACTOR_NONE;
9864 PetscCall(PetscFree(S->solvertype));
9865 }
9866 case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9867 break;
9868 default:
9869 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9870 }
9871 PetscFunctionReturn(PETSC_SUCCESS);
9872 }
9873
9874 /*@
9875 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9876
9877 Logically Collective
9878
9879 Input Parameters:
9880 + F - the factored matrix obtained by calling `MatGetFactor()`
9881 . S - location where the Schur complement is stored
9882 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9883
9884 Level: advanced
9885
9886 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9887 @*/
MatFactorRestoreSchurComplement(Mat F,Mat * S,MatFactorSchurStatus status)9888 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9889 {
9890 PetscFunctionBegin;
9891 PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9892 if (S) {
9893 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9894 *S = NULL;
9895 }
9896 F->schur_status = status;
9897 PetscCall(MatFactorUpdateSchurStatus_Private(F));
9898 PetscFunctionReturn(PETSC_SUCCESS);
9899 }
9900
9901 /*@
9902 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9903
9904 Logically Collective
9905
9906 Input Parameters:
9907 + F - the factored matrix obtained by calling `MatGetFactor()`
9908 . rhs - location where the right-hand side of the Schur complement system is stored
9909 - sol - location where the solution of the Schur complement system has to be returned
9910
9911 Level: advanced
9912
9913 Notes:
9914 The sizes of the vectors should match the size of the Schur complement
9915
9916 Must be called after `MatFactorSetSchurIS()`
9917
9918 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9919 @*/
MatFactorSolveSchurComplementTranspose(Mat F,Vec rhs,Vec sol)9920 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9921 {
9922 PetscFunctionBegin;
9923 PetscValidType(F, 1);
9924 PetscValidType(rhs, 2);
9925 PetscValidType(sol, 3);
9926 PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9927 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9928 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9929 PetscCheckSameComm(F, 1, rhs, 2);
9930 PetscCheckSameComm(F, 1, sol, 3);
9931 PetscCall(MatFactorFactorizeSchurComplement(F));
9932 switch (F->schur_status) {
9933 case MAT_FACTOR_SCHUR_FACTORED:
9934 PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9935 break;
9936 case MAT_FACTOR_SCHUR_INVERTED:
9937 PetscCall(MatMultTranspose(F->schur, rhs, sol));
9938 break;
9939 default:
9940 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9941 }
9942 PetscFunctionReturn(PETSC_SUCCESS);
9943 }
9944
9945 /*@
9946 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9947
9948 Logically Collective
9949
9950 Input Parameters:
9951 + F - the factored matrix obtained by calling `MatGetFactor()`
9952 . rhs - location where the right-hand side of the Schur complement system is stored
9953 - sol - location where the solution of the Schur complement system has to be returned
9954
9955 Level: advanced
9956
9957 Notes:
9958 The sizes of the vectors should match the size of the Schur complement
9959
9960 Must be called after `MatFactorSetSchurIS()`
9961
9962 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9963 @*/
MatFactorSolveSchurComplement(Mat F,Vec rhs,Vec sol)9964 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9965 {
9966 PetscFunctionBegin;
9967 PetscValidType(F, 1);
9968 PetscValidType(rhs, 2);
9969 PetscValidType(sol, 3);
9970 PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9971 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9972 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9973 PetscCheckSameComm(F, 1, rhs, 2);
9974 PetscCheckSameComm(F, 1, sol, 3);
9975 PetscCall(MatFactorFactorizeSchurComplement(F));
9976 switch (F->schur_status) {
9977 case MAT_FACTOR_SCHUR_FACTORED:
9978 PetscCall(MatSolve(F->schur, rhs, sol));
9979 break;
9980 case MAT_FACTOR_SCHUR_INVERTED:
9981 PetscCall(MatMult(F->schur, rhs, sol));
9982 break;
9983 default:
9984 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9985 }
9986 PetscFunctionReturn(PETSC_SUCCESS);
9987 }
9988
9989 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9990 #if PetscDefined(HAVE_CUDA)
9991 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9992 #endif
9993
9994 /* Schur status updated in the interface */
MatFactorInvertSchurComplement_Private(Mat F)9995 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9996 {
9997 Mat S = F->schur;
9998
9999 PetscFunctionBegin;
10000 if (S) {
10001 PetscMPIInt size;
10002 PetscBool isdense, isdensecuda;
10003
10004 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
10005 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
10006 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
10007 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
10008 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
10009 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
10010 if (isdense) {
10011 PetscCall(MatSeqDenseInvertFactors_Private(S));
10012 } else if (isdensecuda) {
10013 #if defined(PETSC_HAVE_CUDA)
10014 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
10015 #endif
10016 }
10017 // HIP??????????????
10018 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
10019 }
10020 PetscFunctionReturn(PETSC_SUCCESS);
10021 }
10022
10023 /*@
10024 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
10025
10026 Logically Collective
10027
10028 Input Parameter:
10029 . F - the factored matrix obtained by calling `MatGetFactor()`
10030
10031 Level: advanced
10032
10033 Notes:
10034 Must be called after `MatFactorSetSchurIS()`.
10035
10036 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
10037
10038 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
10039 @*/
MatFactorInvertSchurComplement(Mat F)10040 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
10041 {
10042 PetscFunctionBegin;
10043 PetscValidType(F, 1);
10044 PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10045 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
10046 PetscCall(MatFactorFactorizeSchurComplement(F));
10047 PetscCall(MatFactorInvertSchurComplement_Private(F));
10048 F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
10049 PetscFunctionReturn(PETSC_SUCCESS);
10050 }
10051
10052 /*@
10053 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
10054
10055 Logically Collective
10056
10057 Input Parameter:
10058 . F - the factored matrix obtained by calling `MatGetFactor()`
10059
10060 Level: advanced
10061
10062 Note:
10063 Must be called after `MatFactorSetSchurIS()`
10064
10065 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
10066 @*/
MatFactorFactorizeSchurComplement(Mat F)10067 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
10068 {
10069 MatFactorInfo info;
10070
10071 PetscFunctionBegin;
10072 PetscValidType(F, 1);
10073 PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10074 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
10075 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
10076 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
10077 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
10078 PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
10079 } else {
10080 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
10081 }
10082 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
10083 F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
10084 PetscFunctionReturn(PETSC_SUCCESS);
10085 }
10086
10087 /*@
10088 MatPtAP - Creates the matrix product $C = P^T * A * P$
10089
10090 Neighbor-wise Collective
10091
10092 Input Parameters:
10093 + A - the matrix
10094 . P - the projection matrix
10095 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10096 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10097 if the result is a dense matrix this is irrelevant
10098
10099 Output Parameter:
10100 . C - the product matrix
10101
10102 Level: intermediate
10103
10104 Notes:
10105 `C` will be created and must be destroyed by the user with `MatDestroy()`.
10106
10107 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_PtAP`
10108 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`.
10109
10110 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10111
10112 Developer Note:
10113 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10114
10115 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10116 @*/
MatPtAP(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat * C)10117 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10118 {
10119 PetscFunctionBegin;
10120 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10121 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10122
10123 if (scall == MAT_INITIAL_MATRIX) {
10124 PetscCall(MatProductCreate(A, P, NULL, C));
10125 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10126 PetscCall(MatProductSetAlgorithm(*C, "default"));
10127 PetscCall(MatProductSetFill(*C, fill));
10128
10129 (*C)->product->api_user = PETSC_TRUE;
10130 PetscCall(MatProductSetFromOptions(*C));
10131 PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "MatProduct %s not supported for A %s and P %s", MatProductTypes[MATPRODUCT_PtAP], ((PetscObject)A)->type_name, ((PetscObject)P)->type_name);
10132 PetscCall(MatProductSymbolic(*C));
10133 } else { /* scall == MAT_REUSE_MATRIX */
10134 PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10135 }
10136
10137 PetscCall(MatProductNumeric(*C));
10138 if (A->symmetric == PETSC_BOOL3_TRUE) {
10139 PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10140 (*C)->spd = A->spd;
10141 }
10142 PetscFunctionReturn(PETSC_SUCCESS);
10143 }
10144
10145 /*@
10146 MatRARt - Creates the matrix product $C = R * A * R^T$
10147
10148 Neighbor-wise Collective
10149
10150 Input Parameters:
10151 + A - the matrix
10152 . R - the projection matrix
10153 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10154 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10155 if the result is a dense matrix this is irrelevant
10156
10157 Output Parameter:
10158 . C - the product matrix
10159
10160 Level: intermediate
10161
10162 Notes:
10163 `C` will be created and must be destroyed by the user with `MatDestroy()`.
10164
10165 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_RARt`
10166 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`.
10167
10168 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10169 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10170 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive.
10171 We recommend using `MatPtAP()` when possible.
10172
10173 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10174
10175 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10176 @*/
MatRARt(Mat A,Mat R,MatReuse scall,PetscReal fill,Mat * C)10177 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10178 {
10179 PetscFunctionBegin;
10180 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10181 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10182
10183 if (scall == MAT_INITIAL_MATRIX) {
10184 PetscCall(MatProductCreate(A, R, NULL, C));
10185 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10186 PetscCall(MatProductSetAlgorithm(*C, "default"));
10187 PetscCall(MatProductSetFill(*C, fill));
10188
10189 (*C)->product->api_user = PETSC_TRUE;
10190 PetscCall(MatProductSetFromOptions(*C));
10191 PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "MatProduct %s not supported for A %s and R %s", MatProductTypes[MATPRODUCT_RARt], ((PetscObject)A)->type_name, ((PetscObject)R)->type_name);
10192 PetscCall(MatProductSymbolic(*C));
10193 } else { /* scall == MAT_REUSE_MATRIX */
10194 PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10195 }
10196
10197 PetscCall(MatProductNumeric(*C));
10198 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10199 PetscFunctionReturn(PETSC_SUCCESS);
10200 }
10201
MatProduct_Private(Mat A,Mat B,MatReuse scall,PetscReal fill,MatProductType ptype,Mat * C)10202 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10203 {
10204 PetscBool flg = PETSC_TRUE;
10205
10206 PetscFunctionBegin;
10207 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10208 if (scall == MAT_INITIAL_MATRIX) {
10209 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10210 PetscCall(MatProductCreate(A, B, NULL, C));
10211 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10212 PetscCall(MatProductSetFill(*C, fill));
10213 } else { /* scall == MAT_REUSE_MATRIX */
10214 Mat_Product *product = (*C)->product;
10215
10216 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10217 if (flg && product && product->type != ptype) {
10218 PetscCall(MatProductClear(*C));
10219 product = NULL;
10220 }
10221 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10222 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10223 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10224 PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10225 product = (*C)->product;
10226 product->fill = fill;
10227 product->clear = PETSC_TRUE;
10228 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10229 flg = PETSC_FALSE;
10230 PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10231 }
10232 }
10233 if (flg) {
10234 (*C)->product->api_user = PETSC_TRUE;
10235 PetscCall(MatProductSetType(*C, ptype));
10236 PetscCall(MatProductSetFromOptions(*C));
10237 PetscCall(MatProductSymbolic(*C));
10238 }
10239 PetscCall(MatProductNumeric(*C));
10240 PetscFunctionReturn(PETSC_SUCCESS);
10241 }
10242
10243 /*@
10244 MatMatMult - Performs matrix-matrix multiplication $ C=A*B $.
10245
10246 Neighbor-wise Collective
10247
10248 Input Parameters:
10249 + A - the left matrix
10250 . B - the right matrix
10251 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10252 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10253 if the result is a dense matrix this is irrelevant
10254
10255 Output Parameter:
10256 . C - the product matrix
10257
10258 Notes:
10259 Unless scall is `MAT_REUSE_MATRIX` C will be created.
10260
10261 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call and C was obtained from a previous
10262 call to this function with `MAT_INITIAL_MATRIX`.
10263
10264 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed.
10265
10266 In the special case where matrix `B` (and hence `C`) are dense you can create the correctly sized matrix `C` yourself and then call this routine with `MAT_REUSE_MATRIX`,
10267 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse.
10268
10269 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10270
10271 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_AB`
10272 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`.
10273
10274 Example of Usage:
10275 .vb
10276 MatProductCreate(A,B,NULL,&C);
10277 MatProductSetType(C,MATPRODUCT_AB);
10278 MatProductSymbolic(C);
10279 MatProductNumeric(C); // compute C=A * B
10280 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10281 MatProductNumeric(C);
10282 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10283 MatProductNumeric(C);
10284 .ve
10285
10286 Level: intermediate
10287
10288 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10289 @*/
MatMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat * C)10290 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10291 {
10292 PetscFunctionBegin;
10293 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10294 PetscFunctionReturn(PETSC_SUCCESS);
10295 }
10296
10297 /*@
10298 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10299
10300 Neighbor-wise Collective
10301
10302 Input Parameters:
10303 + A - the left matrix
10304 . B - the right matrix
10305 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10306 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10307
10308 Output Parameter:
10309 . C - the product matrix
10310
10311 Options Database Key:
10312 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10313 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10314 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10315
10316 Level: intermediate
10317
10318 Notes:
10319 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10320
10321 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10322
10323 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10324 actually needed.
10325
10326 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10327 and for pairs of `MATMPIDENSE` matrices.
10328
10329 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_ABt`
10330 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`.
10331
10332 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10333
10334 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10335 @*/
MatMatTransposeMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat * C)10336 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10337 {
10338 PetscFunctionBegin;
10339 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10340 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10341 PetscFunctionReturn(PETSC_SUCCESS);
10342 }
10343
10344 /*@
10345 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10346
10347 Neighbor-wise Collective
10348
10349 Input Parameters:
10350 + A - the left matrix
10351 . B - the right matrix
10352 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10353 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10354
10355 Output Parameter:
10356 . C - the product matrix
10357
10358 Level: intermediate
10359
10360 Notes:
10361 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10362
10363 `MAT_REUSE_MATRIX` can only be used if `A` and `B` have the same nonzero pattern as in the previous call.
10364
10365 This is a convenience routine that wraps the use of `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_AtB`
10366 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`.
10367
10368 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10369 actually needed.
10370
10371 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10372 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices.
10373
10374 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10375
10376 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10377 @*/
MatTransposeMatMult(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat * C)10378 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10379 {
10380 PetscFunctionBegin;
10381 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10382 PetscFunctionReturn(PETSC_SUCCESS);
10383 }
10384
10385 /*@
10386 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10387
10388 Neighbor-wise Collective
10389
10390 Input Parameters:
10391 + A - the left matrix
10392 . B - the middle matrix
10393 . C - the right matrix
10394 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10395 - fill - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10396 if the result is a dense matrix this is irrelevant
10397
10398 Output Parameter:
10399 . D - the product matrix
10400
10401 Level: intermediate
10402
10403 Notes:
10404 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10405
10406 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10407
10408 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_ABC`
10409 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`.
10410
10411 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10412 actually needed.
10413
10414 If you have many matrices with the same non-zero structure to multiply, you
10415 should use `MAT_REUSE_MATRIX` in all calls but the first
10416
10417 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10418
10419 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10420 @*/
MatMatMatMult(Mat A,Mat B,Mat C,MatReuse scall,PetscReal fill,Mat * D)10421 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10422 {
10423 PetscFunctionBegin;
10424 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10425 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10426
10427 if (scall == MAT_INITIAL_MATRIX) {
10428 PetscCall(MatProductCreate(A, B, C, D));
10429 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10430 PetscCall(MatProductSetAlgorithm(*D, "default"));
10431 PetscCall(MatProductSetFill(*D, fill));
10432
10433 (*D)->product->api_user = PETSC_TRUE;
10434 PetscCall(MatProductSetFromOptions(*D));
10435 PetscCheck((*D)->ops->productsymbolic, PetscObjectComm((PetscObject)*D), PETSC_ERR_SUP, "MatProduct %s not supported for A %s, B %s and C %s", MatProductTypes[MATPRODUCT_ABC], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name,
10436 ((PetscObject)C)->type_name);
10437 PetscCall(MatProductSymbolic(*D));
10438 } else { /* user may change input matrices when REUSE */
10439 PetscCall(MatProductReplaceMats(A, B, C, *D));
10440 }
10441 PetscCall(MatProductNumeric(*D));
10442 PetscFunctionReturn(PETSC_SUCCESS);
10443 }
10444
10445 /*@
10446 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10447
10448 Collective
10449
10450 Input Parameters:
10451 + mat - the matrix
10452 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10453 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10454 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10455
10456 Output Parameter:
10457 . matredundant - redundant matrix
10458
10459 Level: advanced
10460
10461 Notes:
10462 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10463 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10464
10465 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10466 calling it.
10467
10468 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10469
10470 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10471 @*/
MatCreateRedundantMatrix(Mat mat,PetscInt nsubcomm,MPI_Comm subcomm,MatReuse reuse,Mat * matredundant)10472 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10473 {
10474 MPI_Comm comm;
10475 PetscMPIInt size;
10476 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10477 Mat_Redundant *redund = NULL;
10478 PetscSubcomm psubcomm = NULL;
10479 MPI_Comm subcomm_in = subcomm;
10480 Mat *matseq;
10481 IS isrow, iscol;
10482 PetscBool newsubcomm = PETSC_FALSE;
10483
10484 PetscFunctionBegin;
10485 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10486 if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10487 PetscAssertPointer(*matredundant, 5);
10488 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10489 }
10490
10491 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10492 if (size == 1 || nsubcomm == 1) {
10493 if (reuse == MAT_INITIAL_MATRIX) {
10494 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10495 } else {
10496 PetscCheck(*matredundant != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10497 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10498 }
10499 PetscFunctionReturn(PETSC_SUCCESS);
10500 }
10501
10502 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10503 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10504 MatCheckPreallocated(mat, 1);
10505
10506 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10507 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10508 /* create psubcomm, then get subcomm */
10509 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10510 PetscCallMPI(MPI_Comm_size(comm, &size));
10511 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10512
10513 PetscCall(PetscSubcommCreate(comm, &psubcomm));
10514 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10515 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10516 PetscCall(PetscSubcommSetFromOptions(psubcomm));
10517 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10518 newsubcomm = PETSC_TRUE;
10519 PetscCall(PetscSubcommDestroy(&psubcomm));
10520 }
10521
10522 /* get isrow, iscol and a local sequential matrix matseq[0] */
10523 if (reuse == MAT_INITIAL_MATRIX) {
10524 mloc_sub = PETSC_DECIDE;
10525 nloc_sub = PETSC_DECIDE;
10526 if (bs < 1) {
10527 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10528 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10529 } else {
10530 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10531 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10532 }
10533 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10534 rstart = rend - mloc_sub;
10535 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10536 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10537 PetscCall(ISSetIdentity(iscol));
10538 } else { /* reuse == MAT_REUSE_MATRIX */
10539 PetscCheck(*matredundant != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10540 /* retrieve subcomm */
10541 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10542 redund = (*matredundant)->redundant;
10543 isrow = redund->isrow;
10544 iscol = redund->iscol;
10545 matseq = redund->matseq;
10546 }
10547 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10548
10549 /* get matredundant over subcomm */
10550 if (reuse == MAT_INITIAL_MATRIX) {
10551 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10552
10553 /* create a supporting struct and attach it to C for reuse */
10554 PetscCall(PetscNew(&redund));
10555 (*matredundant)->redundant = redund;
10556 redund->isrow = isrow;
10557 redund->iscol = iscol;
10558 redund->matseq = matseq;
10559 if (newsubcomm) {
10560 redund->subcomm = subcomm;
10561 } else {
10562 redund->subcomm = MPI_COMM_NULL;
10563 }
10564 } else {
10565 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10566 }
10567 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10568 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10569 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10570 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10571 }
10572 #endif
10573 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10574 PetscFunctionReturn(PETSC_SUCCESS);
10575 }
10576
10577 /*@C
10578 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10579 a given `Mat`. Each submatrix can span multiple procs.
10580
10581 Collective
10582
10583 Input Parameters:
10584 + mat - the matrix
10585 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10586 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10587
10588 Output Parameter:
10589 . subMat - parallel sub-matrices each spanning a given `subcomm`
10590
10591 Level: advanced
10592
10593 Notes:
10594 The submatrix partition across processors is dictated by `subComm` a
10595 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10596 is not restricted to be grouped with consecutive original MPI processes.
10597
10598 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10599 map directly to the layout of the original matrix [wrt the local
10600 row,col partitioning]. So the original 'DiagonalMat' naturally maps
10601 into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10602 the `subMat`. However the offDiagMat looses some columns - and this is
10603 reconstructed with `MatSetValues()`
10604
10605 This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10606
10607 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10608 @*/
MatGetMultiProcBlock(Mat mat,MPI_Comm subComm,MatReuse scall,Mat * subMat)10609 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10610 {
10611 PetscMPIInt commsize, subCommSize;
10612
10613 PetscFunctionBegin;
10614 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10615 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10616 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10617
10618 PetscCheck(scall != MAT_REUSE_MATRIX || *subMat != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10619 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10620 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10621 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10622 PetscFunctionReturn(PETSC_SUCCESS);
10623 }
10624
10625 /*@
10626 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10627
10628 Not Collective
10629
10630 Input Parameters:
10631 + mat - matrix to extract local submatrix from
10632 . isrow - local row indices for submatrix
10633 - iscol - local column indices for submatrix
10634
10635 Output Parameter:
10636 . submat - the submatrix
10637
10638 Level: intermediate
10639
10640 Notes:
10641 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10642
10643 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be
10644 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10645
10646 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then
10647 `MatSetValuesBlockedLocal()` will also be implemented.
10648
10649 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10650 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10651
10652 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10653 @*/
MatGetLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat * submat)10654 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10655 {
10656 PetscFunctionBegin;
10657 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10658 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10659 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10660 PetscCheckSameComm(isrow, 2, iscol, 3);
10661 PetscAssertPointer(submat, 4);
10662 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10663
10664 if (mat->ops->getlocalsubmatrix) {
10665 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10666 } else {
10667 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10668 }
10669 (*submat)->assembled = mat->assembled;
10670 PetscFunctionReturn(PETSC_SUCCESS);
10671 }
10672
10673 /*@
10674 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10675
10676 Not Collective
10677
10678 Input Parameters:
10679 + mat - matrix to extract local submatrix from
10680 . isrow - local row indices for submatrix
10681 . iscol - local column indices for submatrix
10682 - submat - the submatrix
10683
10684 Level: intermediate
10685
10686 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10687 @*/
MatRestoreLocalSubMatrix(Mat mat,IS isrow,IS iscol,Mat * submat)10688 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10689 {
10690 PetscFunctionBegin;
10691 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10692 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10693 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10694 PetscCheckSameComm(isrow, 2, iscol, 3);
10695 PetscAssertPointer(submat, 4);
10696 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10697
10698 if (mat->ops->restorelocalsubmatrix) {
10699 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10700 } else {
10701 PetscCall(MatDestroy(submat));
10702 }
10703 *submat = NULL;
10704 PetscFunctionReturn(PETSC_SUCCESS);
10705 }
10706
10707 /*@
10708 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10709
10710 Collective
10711
10712 Input Parameter:
10713 . mat - the matrix
10714
10715 Output Parameter:
10716 . is - if any rows have zero diagonals this contains the list of them
10717
10718 Level: developer
10719
10720 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10721 @*/
MatFindZeroDiagonals(Mat mat,IS * is)10722 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10723 {
10724 PetscFunctionBegin;
10725 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10726 PetscValidType(mat, 1);
10727 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10728 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10729
10730 if (!mat->ops->findzerodiagonals) {
10731 Vec diag;
10732 const PetscScalar *a;
10733 PetscInt *rows;
10734 PetscInt rStart, rEnd, r, nrow = 0;
10735
10736 PetscCall(MatCreateVecs(mat, &diag, NULL));
10737 PetscCall(MatGetDiagonal(mat, diag));
10738 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10739 PetscCall(VecGetArrayRead(diag, &a));
10740 for (r = 0; r < rEnd - rStart; ++r)
10741 if (a[r] == 0.0) ++nrow;
10742 PetscCall(PetscMalloc1(nrow, &rows));
10743 nrow = 0;
10744 for (r = 0; r < rEnd - rStart; ++r)
10745 if (a[r] == 0.0) rows[nrow++] = r + rStart;
10746 PetscCall(VecRestoreArrayRead(diag, &a));
10747 PetscCall(VecDestroy(&diag));
10748 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10749 } else {
10750 PetscUseTypeMethod(mat, findzerodiagonals, is);
10751 }
10752 PetscFunctionReturn(PETSC_SUCCESS);
10753 }
10754
10755 /*@
10756 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10757
10758 Collective
10759
10760 Input Parameter:
10761 . mat - the matrix
10762
10763 Output Parameter:
10764 . is - contains the list of rows with off block diagonal entries
10765
10766 Level: developer
10767
10768 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10769 @*/
MatFindOffBlockDiagonalEntries(Mat mat,IS * is)10770 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10771 {
10772 PetscFunctionBegin;
10773 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10774 PetscValidType(mat, 1);
10775 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10776 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10777
10778 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10779 PetscFunctionReturn(PETSC_SUCCESS);
10780 }
10781
10782 /*@C
10783 MatInvertBlockDiagonal - Inverts the block diagonal entries.
10784
10785 Collective; No Fortran Support
10786
10787 Input Parameter:
10788 . mat - the matrix
10789
10790 Output Parameter:
10791 . values - the block inverses in column major order (FORTRAN-like)
10792
10793 Level: advanced
10794
10795 Notes:
10796 The size of the blocks is determined by the block size of the matrix.
10797
10798 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10799
10800 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10801
10802 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10803 @*/
MatInvertBlockDiagonal(Mat mat,const PetscScalar * values[])10804 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10805 {
10806 PetscFunctionBegin;
10807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10808 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10809 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10810 PetscUseTypeMethod(mat, invertblockdiagonal, values);
10811 PetscFunctionReturn(PETSC_SUCCESS);
10812 }
10813
10814 /*@
10815 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10816
10817 Collective; No Fortran Support
10818
10819 Input Parameters:
10820 + mat - the matrix
10821 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10822 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10823
10824 Output Parameter:
10825 . values - the block inverses in column major order (FORTRAN-like)
10826
10827 Level: advanced
10828
10829 Notes:
10830 Use `MatInvertBlockDiagonal()` if all blocks have the same size
10831
10832 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10833
10834 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10835 @*/
MatInvertVariableBlockDiagonal(Mat mat,PetscInt nblocks,const PetscInt bsizes[],PetscScalar values[])10836 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10837 {
10838 PetscFunctionBegin;
10839 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10840 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10841 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10842 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10843 PetscFunctionReturn(PETSC_SUCCESS);
10844 }
10845
10846 /*@
10847 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10848
10849 Collective
10850
10851 Input Parameters:
10852 + A - the matrix
10853 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set.
10854
10855 Level: advanced
10856
10857 Note:
10858 The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10859
10860 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10861 @*/
MatInvertBlockDiagonalMat(Mat A,Mat C)10862 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10863 {
10864 const PetscScalar *vals;
10865 PetscInt *dnnz;
10866 PetscInt m, rstart, rend, bs, i, j;
10867
10868 PetscFunctionBegin;
10869 PetscCall(MatInvertBlockDiagonal(A, &vals));
10870 PetscCall(MatGetBlockSize(A, &bs));
10871 PetscCall(MatGetLocalSize(A, &m, NULL));
10872 PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10873 PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs));
10874 PetscCall(PetscMalloc1(m / bs, &dnnz));
10875 for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10876 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10877 PetscCall(PetscFree(dnnz));
10878 PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10879 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10880 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10881 PetscCall(MatSetOption(C, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
10882 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10883 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10884 PetscCall(MatSetOption(C, MAT_NO_OFF_PROC_ENTRIES, PETSC_FALSE));
10885 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10886 PetscFunctionReturn(PETSC_SUCCESS);
10887 }
10888
10889 /*@
10890 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10891 via `MatTransposeColoringCreate()`.
10892
10893 Collective
10894
10895 Input Parameter:
10896 . c - coloring context
10897
10898 Level: intermediate
10899
10900 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10901 @*/
MatTransposeColoringDestroy(MatTransposeColoring * c)10902 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10903 {
10904 MatTransposeColoring matcolor = *c;
10905
10906 PetscFunctionBegin;
10907 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10908 if (--((PetscObject)matcolor)->refct > 0) {
10909 matcolor = NULL;
10910 PetscFunctionReturn(PETSC_SUCCESS);
10911 }
10912
10913 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10914 PetscCall(PetscFree(matcolor->rows));
10915 PetscCall(PetscFree(matcolor->den2sp));
10916 PetscCall(PetscFree(matcolor->colorforcol));
10917 PetscCall(PetscFree(matcolor->columns));
10918 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10919 PetscCall(PetscHeaderDestroy(c));
10920 PetscFunctionReturn(PETSC_SUCCESS);
10921 }
10922
10923 /*@
10924 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10925 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10926 `MatTransposeColoring` to sparse `B`.
10927
10928 Collective
10929
10930 Input Parameters:
10931 + coloring - coloring context created with `MatTransposeColoringCreate()`
10932 - B - sparse matrix
10933
10934 Output Parameter:
10935 . Btdense - dense matrix $B^T$
10936
10937 Level: developer
10938
10939 Note:
10940 These are used internally for some implementations of `MatRARt()`
10941
10942 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10943 @*/
MatTransColoringApplySpToDen(MatTransposeColoring coloring,Mat B,Mat Btdense)10944 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10945 {
10946 PetscFunctionBegin;
10947 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10948 PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10949 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10950
10951 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10952 PetscFunctionReturn(PETSC_SUCCESS);
10953 }
10954
10955 /*@
10956 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10957 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10958 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10959 $C_{sp}$ from $C_{den}$.
10960
10961 Collective
10962
10963 Input Parameters:
10964 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10965 - Cden - matrix product of a sparse matrix and a dense matrix Btdense
10966
10967 Output Parameter:
10968 . Csp - sparse matrix
10969
10970 Level: developer
10971
10972 Note:
10973 These are used internally for some implementations of `MatRARt()`
10974
10975 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10976 @*/
MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring,Mat Cden,Mat Csp)10977 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10978 {
10979 PetscFunctionBegin;
10980 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10981 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10982 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10983
10984 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10985 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10986 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10987 PetscFunctionReturn(PETSC_SUCCESS);
10988 }
10989
10990 /*@
10991 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10992
10993 Collective
10994
10995 Input Parameters:
10996 + mat - the matrix product C
10997 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10998
10999 Output Parameter:
11000 . color - the new coloring context
11001
11002 Level: intermediate
11003
11004 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
11005 `MatTransColoringApplyDenToSp()`
11006 @*/
MatTransposeColoringCreate(Mat mat,ISColoring iscoloring,MatTransposeColoring * color)11007 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
11008 {
11009 MatTransposeColoring c;
11010 MPI_Comm comm;
11011
11012 PetscFunctionBegin;
11013 PetscAssertPointer(color, 3);
11014
11015 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11016 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
11017 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
11018 c->ctype = iscoloring->ctype;
11019 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
11020 *color = c;
11021 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11022 PetscFunctionReturn(PETSC_SUCCESS);
11023 }
11024
11025 /*@
11026 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
11027 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
11028
11029 Not Collective
11030
11031 Input Parameter:
11032 . mat - the matrix
11033
11034 Output Parameter:
11035 . state - the current state
11036
11037 Level: intermediate
11038
11039 Notes:
11040 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
11041 different matrices
11042
11043 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
11044
11045 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
11046
11047 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
11048 @*/
MatGetNonzeroState(Mat mat,PetscObjectState * state)11049 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
11050 {
11051 PetscFunctionBegin;
11052 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11053 *state = mat->nonzerostate;
11054 PetscFunctionReturn(PETSC_SUCCESS);
11055 }
11056
11057 /*@
11058 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
11059 matrices from each processor
11060
11061 Collective
11062
11063 Input Parameters:
11064 + comm - the communicators the parallel matrix will live on
11065 . seqmat - the input sequential matrices
11066 . n - number of local columns (or `PETSC_DECIDE`)
11067 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11068
11069 Output Parameter:
11070 . mpimat - the parallel matrix generated
11071
11072 Level: developer
11073
11074 Note:
11075 The number of columns of the matrix in EACH processor MUST be the same.
11076
11077 .seealso: [](ch_matrices), `Mat`
11078 @*/
MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm,Mat seqmat,PetscInt n,MatReuse reuse,Mat * mpimat)11079 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
11080 {
11081 PetscMPIInt size;
11082
11083 PetscFunctionBegin;
11084 PetscCallMPI(MPI_Comm_size(comm, &size));
11085 if (size == 1) {
11086 if (reuse == MAT_INITIAL_MATRIX) {
11087 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
11088 } else {
11089 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
11090 }
11091 PetscFunctionReturn(PETSC_SUCCESS);
11092 }
11093
11094 PetscCheck(reuse != MAT_REUSE_MATRIX || seqmat != *mpimat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
11095
11096 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
11097 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
11098 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
11099 PetscFunctionReturn(PETSC_SUCCESS);
11100 }
11101
11102 /*@
11103 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
11104
11105 Collective
11106
11107 Input Parameters:
11108 + A - the matrix to create subdomains from
11109 - N - requested number of subdomains
11110
11111 Output Parameters:
11112 + n - number of subdomains resulting on this MPI process
11113 - iss - `IS` list with indices of subdomains on this MPI process
11114
11115 Level: advanced
11116
11117 Note:
11118 The number of subdomains must be smaller than the communicator size
11119
11120 .seealso: [](ch_matrices), `Mat`, `IS`
11121 @*/
MatSubdomainsCreateCoalesce(Mat A,PetscInt N,PetscInt * n,IS * iss[])11122 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11123 {
11124 MPI_Comm comm, subcomm;
11125 PetscMPIInt size, rank, color;
11126 PetscInt rstart, rend, k;
11127
11128 PetscFunctionBegin;
11129 PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11130 PetscCallMPI(MPI_Comm_size(comm, &size));
11131 PetscCallMPI(MPI_Comm_rank(comm, &rank));
11132 PetscCheck(N >= 1 && N < size, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subdomains must be > 0 and < %d, got N = %" PetscInt_FMT, size, N);
11133 *n = 1;
11134 k = size / N + (size % N > 0); /* There are up to k ranks to a color */
11135 color = rank / k;
11136 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11137 PetscCall(PetscMalloc1(1, iss));
11138 PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11139 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11140 PetscCallMPI(MPI_Comm_free(&subcomm));
11141 PetscFunctionReturn(PETSC_SUCCESS);
11142 }
11143
11144 /*@
11145 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11146
11147 If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11148 If they are not the same, uses `MatMatMatMult()`.
11149
11150 Once the coarse grid problem is constructed, correct for interpolation operators
11151 that are not of full rank, which can legitimately happen in the case of non-nested
11152 geometric multigrid.
11153
11154 Input Parameters:
11155 + restrct - restriction operator
11156 . dA - fine grid matrix
11157 . interpolate - interpolation operator
11158 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11159 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate
11160
11161 Output Parameter:
11162 . A - the Galerkin coarse matrix
11163
11164 Options Database Key:
11165 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11166
11167 Level: developer
11168
11169 Note:
11170 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
11171
11172 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11173 @*/
MatGalerkin(Mat restrct,Mat dA,Mat interpolate,MatReuse reuse,PetscReal fill,Mat * A)11174 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11175 {
11176 IS zerorows;
11177 Vec diag;
11178
11179 PetscFunctionBegin;
11180 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11181 /* Construct the coarse grid matrix */
11182 if (interpolate == restrct) {
11183 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11184 } else {
11185 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11186 }
11187
11188 /* If the interpolation matrix is not of full rank, A will have zero rows.
11189 This can legitimately happen in the case of non-nested geometric multigrid.
11190 In that event, we set the rows of the matrix to the rows of the identity,
11191 ignoring the equations (as the RHS will also be zero). */
11192
11193 PetscCall(MatFindZeroRows(*A, &zerorows));
11194
11195 if (zerorows != NULL) { /* if there are any zero rows */
11196 PetscCall(MatCreateVecs(*A, &diag, NULL));
11197 PetscCall(MatGetDiagonal(*A, diag));
11198 PetscCall(VecISSet(diag, zerorows, 1.0));
11199 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11200 PetscCall(VecDestroy(&diag));
11201 PetscCall(ISDestroy(&zerorows));
11202 }
11203 PetscFunctionReturn(PETSC_SUCCESS);
11204 }
11205
11206 /*@C
11207 MatSetOperation - Allows user to set a matrix operation for any matrix type
11208
11209 Logically Collective
11210
11211 Input Parameters:
11212 + mat - the matrix
11213 . op - the name of the operation
11214 - f - the function that provides the operation
11215
11216 Level: developer
11217
11218 Example Usage:
11219 .vb
11220 extern PetscErrorCode usermult(Mat, Vec, Vec);
11221
11222 PetscCall(MatCreateXXX(comm, ..., &A));
11223 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscErrorCodeFn *)usermult));
11224 .ve
11225
11226 Notes:
11227 See the file `include/petscmat.h` for a complete list of matrix
11228 operations, which all have the form MATOP_<OPERATION>, where
11229 <OPERATION> is the name (in all capital letters) of the
11230 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11231
11232 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11233 sequence as the usual matrix interface routines, since they
11234 are intended to be accessed via the usual matrix interface
11235 routines, e.g.,
11236 .vb
11237 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11238 .ve
11239
11240 In particular each function MUST return `PETSC_SUCCESS` on success and
11241 nonzero on failure.
11242
11243 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11244
11245 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11246 @*/
MatSetOperation(Mat mat,MatOperation op,PetscErrorCodeFn * f)11247 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, PetscErrorCodeFn *f)
11248 {
11249 PetscFunctionBegin;
11250 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11251 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (PetscErrorCodeFn *)mat->ops->view) mat->ops->viewnative = mat->ops->view;
11252 (((PetscErrorCodeFn **)mat->ops)[op]) = f;
11253 PetscFunctionReturn(PETSC_SUCCESS);
11254 }
11255
11256 /*@C
11257 MatGetOperation - Gets a matrix operation for any matrix type.
11258
11259 Not Collective
11260
11261 Input Parameters:
11262 + mat - the matrix
11263 - op - the name of the operation
11264
11265 Output Parameter:
11266 . f - the function that provides the operation
11267
11268 Level: developer
11269
11270 Example Usage:
11271 .vb
11272 PetscErrorCode (*usermult)(Mat, Vec, Vec);
11273
11274 MatGetOperation(A, MATOP_MULT, (PetscErrorCodeFn **)&usermult);
11275 .ve
11276
11277 Notes:
11278 See the file `include/petscmat.h` for a complete list of matrix
11279 operations, which all have the form MATOP_<OPERATION>, where
11280 <OPERATION> is the name (in all capital letters) of the
11281 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11282
11283 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11284
11285 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11286 @*/
MatGetOperation(Mat mat,MatOperation op,PetscErrorCodeFn ** f)11287 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, PetscErrorCodeFn **f)
11288 {
11289 PetscFunctionBegin;
11290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11291 *f = (((PetscErrorCodeFn **)mat->ops)[op]);
11292 PetscFunctionReturn(PETSC_SUCCESS);
11293 }
11294
11295 /*@
11296 MatHasOperation - Determines whether the given matrix supports the particular operation.
11297
11298 Not Collective
11299
11300 Input Parameters:
11301 + mat - the matrix
11302 - op - the operation, for example, `MATOP_GET_DIAGONAL`
11303
11304 Output Parameter:
11305 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11306
11307 Level: advanced
11308
11309 Note:
11310 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11311
11312 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11313 @*/
MatHasOperation(Mat mat,MatOperation op,PetscBool * has)11314 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11315 {
11316 PetscFunctionBegin;
11317 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11318 PetscAssertPointer(has, 3);
11319 if (mat->ops->hasoperation) {
11320 PetscUseTypeMethod(mat, hasoperation, op, has);
11321 } else {
11322 if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11323 else {
11324 *has = PETSC_FALSE;
11325 if (op == MATOP_CREATE_SUBMATRIX) {
11326 PetscMPIInt size;
11327
11328 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11329 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11330 }
11331 }
11332 }
11333 PetscFunctionReturn(PETSC_SUCCESS);
11334 }
11335
11336 /*@
11337 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11338
11339 Collective
11340
11341 Input Parameter:
11342 . mat - the matrix
11343
11344 Output Parameter:
11345 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11346
11347 Level: beginner
11348
11349 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11350 @*/
MatHasCongruentLayouts(Mat mat,PetscBool * cong)11351 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11352 {
11353 PetscFunctionBegin;
11354 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11355 PetscValidType(mat, 1);
11356 PetscAssertPointer(cong, 2);
11357 if (!mat->rmap || !mat->cmap) {
11358 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11359 PetscFunctionReturn(PETSC_SUCCESS);
11360 }
11361 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11362 PetscCall(PetscLayoutSetUp(mat->rmap));
11363 PetscCall(PetscLayoutSetUp(mat->cmap));
11364 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11365 if (*cong) mat->congruentlayouts = 1;
11366 else mat->congruentlayouts = 0;
11367 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11368 PetscFunctionReturn(PETSC_SUCCESS);
11369 }
11370
MatSetInf(Mat A)11371 PetscErrorCode MatSetInf(Mat A)
11372 {
11373 PetscFunctionBegin;
11374 PetscUseTypeMethod(A, setinf);
11375 PetscFunctionReturn(PETSC_SUCCESS);
11376 }
11377
11378 /*@
11379 MatCreateGraph - create a scalar matrix (that is a matrix with one vertex for each block vertex in the original matrix), for use in graph algorithms
11380 and possibly removes small values from the graph structure.
11381
11382 Collective
11383
11384 Input Parameters:
11385 + A - the matrix
11386 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11387 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11388 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11389 . num_idx - size of 'index' array
11390 - index - array of block indices to use for graph strength of connection weight
11391
11392 Output Parameter:
11393 . graph - the resulting graph
11394
11395 Level: advanced
11396
11397 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11398 @*/
MatCreateGraph(Mat A,PetscBool sym,PetscBool scale,PetscReal filter,PetscInt num_idx,PetscInt index[],Mat * graph)11399 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11400 {
11401 PetscFunctionBegin;
11402 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11403 PetscValidType(A, 1);
11404 PetscValidLogicalCollectiveBool(A, scale, 3);
11405 PetscAssertPointer(graph, 7);
11406 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0));
11407 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11408 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0));
11409 PetscFunctionReturn(PETSC_SUCCESS);
11410 }
11411
11412 /*@
11413 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11414 meaning the same memory is used for the matrix, and no new memory is allocated.
11415
11416 Collective
11417
11418 Input Parameters:
11419 + A - the matrix
11420 - keep - if for a given row of `A`, the diagonal coefficient is zero, indicates whether it should be left in the structure or eliminated as well
11421
11422 Level: intermediate
11423
11424 Developer Note:
11425 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11426 of the arrays in the data structure are unneeded.
11427
11428 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11429 @*/
MatEliminateZeros(Mat A,PetscBool keep)11430 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11431 {
11432 PetscFunctionBegin;
11433 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11434 PetscUseTypeMethod(A, eliminatezeros, keep);
11435 PetscFunctionReturn(PETSC_SUCCESS);
11436 }
11437
11438 /*@C
11439 MatGetCurrentMemType - Get the memory location of the matrix
11440
11441 Not Collective, but the result will be the same on all MPI processes
11442
11443 Input Parameter:
11444 . A - the matrix whose memory type we are checking
11445
11446 Output Parameter:
11447 . m - the memory type
11448
11449 Level: intermediate
11450
11451 .seealso: [](ch_matrices), `Mat`, `MatBoundToCPU()`, `PetscMemType`
11452 @*/
MatGetCurrentMemType(Mat A,PetscMemType * m)11453 PetscErrorCode MatGetCurrentMemType(Mat A, PetscMemType *m)
11454 {
11455 PetscFunctionBegin;
11456 PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11457 PetscAssertPointer(m, 2);
11458 if (A->ops->getcurrentmemtype) PetscUseTypeMethod(A, getcurrentmemtype, m);
11459 else *m = PETSC_MEMTYPE_HOST;
11460 PetscFunctionReturn(PETSC_SUCCESS);
11461 }
11462