Actual source code: matrix.c
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: */
7: #include <petsc/private/matimpl.h>
8: #include <petsc/private/isimpl.h>
9: #include <petsc/private/vecimpl.h>
11: /* Logging support */
12: PetscClassId MAT_CLASSID;
13: PetscClassId MAT_COLORING_CLASSID;
14: PetscClassId MAT_FDCOLORING_CLASSID;
15: PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
17: PetscLogEvent MAT_Mult, MAT_Mults, 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_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34: PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35: PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
36: PetscLogEvent MAT_GetMultiProcBlock;
37: PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
38: PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
39: PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
40: PetscLogEvent MAT_SetValuesBatch;
41: PetscLogEvent MAT_ViennaCLCopyToGPU;
42: PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43: PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44: PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45: PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46: PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
48: const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
50: /*@
51: MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
52: for sparse matrices that already have locations it fills the locations with random numbers
54: Logically Collective on mat
56: Input Parameters:
57: + x - the matrix
58: - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and
59: it will create one internally.
61: Output Parameter:
62: . x - the matrix
64: Example of Usage:
65: .vb
66: PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
67: MatSetRandom(x,rctx);
68: PetscRandomDestroy(rctx);
69: .ve
71: Level: intermediate
73: .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
74: @*/
75: PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
76: {
77: PetscRandom randObj = NULL;
82: MatCheckPreallocated(x, 1);
84: if (!rctx) {
85: MPI_Comm comm;
86: PetscObjectGetComm((PetscObject)x, &comm);
87: PetscRandomCreate(comm, &randObj);
88: PetscRandomSetType(randObj, x->defaultrandtype);
89: PetscRandomSetFromOptions(randObj);
90: rctx = randObj;
91: }
92: PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0);
93: PetscUseTypeMethod(x, setrandom, rctx);
94: PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0);
96: MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY);
97: MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY);
98: PetscRandomDestroy(&randObj);
99: return 0;
100: }
102: /*@
103: MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
105: Logically Collective on mat
107: Input Parameter:
108: . mat - the factored matrix
110: Output Parameters:
111: + pivot - the pivot value computed
112: - row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
113: the share the matrix
115: Level: advanced
117: Notes:
118: This routine does not work for factorizations done with external packages.
120: This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
122: This can be called on non-factored matrices that come from, for example, matrices used in SOR.
124: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
125: `MAT_FACTOR_NUMERIC_ZEROPIVOT`
126: @*/
127: PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
128: {
132: *pivot = mat->factorerror_zeropivot_value;
133: *row = mat->factorerror_zeropivot_row;
134: return 0;
135: }
137: /*@
138: MatFactorGetError - gets the error code from a factorization
140: Logically Collective on mat
142: Input Parameters:
143: . mat - the factored matrix
145: Output Parameter:
146: . err - the error code
148: Level: advanced
150: Note:
151: This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
153: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
154: `MatFactorError`
155: @*/
156: PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
157: {
160: *err = mat->factorerrortype;
161: return 0;
162: }
164: /*@
165: MatFactorClearError - clears the error code in a factorization
167: Logically Collective on mat
169: Input Parameter:
170: . mat - the factored matrix
172: Level: developer
174: Note:
175: This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
177: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
178: `MatGetErrorCode()`, `MatFactorError`
179: @*/
180: PetscErrorCode MatFactorClearError(Mat mat)
181: {
183: mat->factorerrortype = MAT_FACTOR_NOERROR;
184: mat->factorerror_zeropivot_value = 0.0;
185: mat->factorerror_zeropivot_row = 0;
186: return 0;
187: }
189: PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
190: {
191: Vec r, l;
192: const PetscScalar *al;
193: PetscInt i, nz, gnz, N, n;
195: MatCreateVecs(mat, &r, &l);
196: if (!cols) { /* nonzero rows */
197: MatGetSize(mat, &N, NULL);
198: MatGetLocalSize(mat, &n, NULL);
199: VecSet(l, 0.0);
200: VecSetRandom(r, NULL);
201: MatMult(mat, r, l);
202: VecGetArrayRead(l, &al);
203: } else { /* nonzero columns */
204: MatGetSize(mat, NULL, &N);
205: MatGetLocalSize(mat, NULL, &n);
206: VecSet(r, 0.0);
207: VecSetRandom(l, NULL);
208: MatMultTranspose(mat, l, r);
209: VecGetArrayRead(r, &al);
210: }
211: if (tol <= 0.0) {
212: for (i = 0, nz = 0; i < n; i++)
213: if (al[i] != 0.0) nz++;
214: } else {
215: for (i = 0, nz = 0; i < n; i++)
216: if (PetscAbsScalar(al[i]) > tol) nz++;
217: }
218: MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
219: if (gnz != N) {
220: PetscInt *nzr;
221: PetscMalloc1(nz, &nzr);
222: if (nz) {
223: if (tol < 0) {
224: for (i = 0, nz = 0; i < n; i++)
225: if (al[i] != 0.0) nzr[nz++] = i;
226: } else {
227: for (i = 0, nz = 0; i < n; i++)
228: if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
229: }
230: }
231: ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero);
232: } else *nonzero = NULL;
233: if (!cols) { /* nonzero rows */
234: VecRestoreArrayRead(l, &al);
235: } else {
236: VecRestoreArrayRead(r, &al);
237: }
238: VecDestroy(&l);
239: VecDestroy(&r);
240: return 0;
241: }
243: /*@
244: MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
246: Input Parameter:
247: . A - the matrix
249: Output Parameter:
250: . keptrows - the rows that are not completely zero
252: Note:
253: keptrows is set to NULL if all rows are nonzero.
255: Level: intermediate
257: .seealso: `Mat`, `MatFindZeroRows()`
258: @*/
259: PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
260: {
266: if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
267: else MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows);
268: return 0;
269: }
271: /*@
272: MatFindZeroRows - Locate all rows that are completely zero in the matrix
274: Input Parameter:
275: . A - the matrix
277: Output Parameter:
278: . zerorows - the rows that are completely zero
280: Note:
281: zerorows is set to NULL if no rows are zero.
283: Level: intermediate
285: .seealso: `Mat`, `MatFindNonzeroRows()`
286: @*/
287: PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
288: {
289: IS keptrows;
290: PetscInt m, n;
295: MatFindNonzeroRows(mat, &keptrows);
296: /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
297: In keeping with this convention, we set zerorows to NULL if there are no zero
298: rows. */
299: if (keptrows == NULL) {
300: *zerorows = NULL;
301: } else {
302: MatGetOwnershipRange(mat, &m, &n);
303: ISComplement(keptrows, m, n, zerorows);
304: ISDestroy(&keptrows);
305: }
306: return 0;
307: }
309: /*@
310: MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
312: Not Collective
314: Input Parameters:
315: . A - the matrix
317: Output Parameters:
318: . a - the diagonal part (which is a SEQUENTIAL matrix)
320: Notes:
321: See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
323: Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation.
325: Level: advanced
327: .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
328: @*/
329: PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
330: {
335: if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
336: else {
337: PetscMPIInt size;
339: MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);
341: *a = A;
342: }
343: return 0;
344: }
346: /*@
347: MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
349: Collective on mat
351: Input Parameters:
352: . mat - the matrix
354: Output Parameter:
355: . trace - the sum of the diagonal entries
357: Level: advanced
359: .seealso: `Mat`
360: @*/
361: PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
362: {
363: Vec diag;
367: MatCreateVecs(mat, &diag, NULL);
368: MatGetDiagonal(mat, diag);
369: VecSum(diag, trace);
370: VecDestroy(&diag);
371: return 0;
372: }
374: /*@
375: MatRealPart - Zeros out the imaginary part of the matrix
377: Logically Collective on mat
379: Input Parameters:
380: . mat - the matrix
382: Level: advanced
384: .seealso: `MatImaginaryPart()`
385: @*/
386: PetscErrorCode MatRealPart(Mat mat)
387: {
392: MatCheckPreallocated(mat, 1);
393: PetscUseTypeMethod(mat, realpart);
394: return 0;
395: }
397: /*@C
398: MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
400: Collective on mat
402: Input Parameter:
403: . mat - the matrix
405: Output Parameters:
406: + nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
407: - ghosts - the global indices of the ghost points
409: Note:
410: the nghosts and ghosts are suitable to pass into `VecCreateGhost()`
412: Level: advanced
414: .seealso: `Mat`, `VecCreateGhost()`
415: @*/
416: PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
417: {
422: if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
423: else {
424: if (nghosts) *nghosts = 0;
425: if (ghosts) *ghosts = NULL;
426: }
427: return 0;
428: }
430: /*@
431: MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
433: Logically Collective on mat
435: Input Parameters:
436: . mat - the matrix
438: Level: advanced
440: .seealso: `MatRealPart()`
441: @*/
442: PetscErrorCode MatImaginaryPart(Mat mat)
443: {
448: MatCheckPreallocated(mat, 1);
449: PetscUseTypeMethod(mat, imaginarypart);
450: return 0;
451: }
453: /*@
454: MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
456: Not Collective
458: Input Parameter:
459: . mat - the matrix
461: Output Parameters:
462: + missing - is any diagonal missing
463: - dd - first diagonal entry that is missing (optional) on this process
465: Level: advanced
467: .seealso: `Mat`
468: @*/
469: PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
470: {
476: PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
477: return 0;
478: }
480: /*@C
481: MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()`
482: for each row that you get to ensure that your application does
483: not bleed memory.
485: Not Collective
487: Input Parameters:
488: + mat - the matrix
489: - row - the row to get
491: Output Parameters:
492: + ncols - if not NULL, the number of nonzeros in the row
493: . cols - if not NULL, the column numbers
494: - vals - if not NULL, the values
496: Notes:
497: This routine is provided for people who need to have direct access
498: to the structure of a matrix. We hope that we provide enough
499: high-level matrix routines that few users will need it.
501: `MatGetRow()` always returns 0-based column indices, regardless of
502: whether the internal representation is 0-based (default) or 1-based.
504: For better efficiency, set cols and/or vals to NULL if you do
505: not wish to extract these quantities.
507: The user can only examine the values extracted with `MatGetRow()`;
508: the values cannot be altered. To change the matrix entries, one
509: must use `MatSetValues()`.
511: You can only have one call to `MatGetRow()` outstanding for a particular
512: matrix at a time, per processor. `MatGetRow()` can only obtain rows
513: associated with the given processor, it cannot get rows from the
514: other processors; for that we suggest using `MatCreateSubMatrices()`, then
515: MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
516: is in the global number of rows.
518: Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
520: Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
522: Fortran Note:
523: The calling sequence from Fortran is
524: .vb
525: MatGetRow(matrix,row,ncols,cols,values,ierr)
526: Mat matrix (input)
527: integer row (input)
528: integer ncols (output)
529: integer cols(maxcols) (output)
530: double precision (or double complex) values(maxcols) output
531: .ve
532: where maxcols >= maximum nonzeros in any row of the matrix.
534: Caution:
535: Do not try to change the contents of the output arrays (cols and vals).
536: In some cases, this may corrupt the matrix.
538: Level: advanced
540: .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
541: @*/
542: PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
543: {
544: PetscInt incols;
550: MatCheckPreallocated(mat, 1);
552: PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0);
553: (*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
554: if (ncols) *ncols = incols;
555: PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0);
556: return 0;
557: }
559: /*@
560: MatConjugate - replaces the matrix values with their complex conjugates
562: Logically Collective on mat
564: Input Parameters:
565: . mat - the matrix
567: Level: advanced
569: .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
570: @*/
571: PetscErrorCode MatConjugate(Mat mat)
572: {
575: if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
576: PetscUseTypeMethod(mat, conjugate);
577: PetscObjectStateIncrease((PetscObject)mat);
578: }
579: return 0;
580: }
582: /*@C
583: MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
585: Not Collective
587: Input Parameters:
588: + mat - the matrix
589: . row - the row to get
590: . ncols, cols - the number of nonzeros and their columns
591: - vals - if nonzero the column values
593: Notes:
594: This routine should be called after you have finished examining the entries.
596: This routine zeros out ncols, cols, and vals. This is to prevent accidental
597: us of the array after it has been restored. If you pass NULL, it will
598: not zero the pointers. Use of cols or vals after `MatRestoreRow()` is invalid.
600: Fortran Notes:
601: The calling sequence from Fortran is
602: .vb
603: MatRestoreRow(matrix,row,ncols,cols,values,ierr)
604: Mat matrix (input)
605: integer row (input)
606: integer ncols (output)
607: integer cols(maxcols) (output)
608: double precision (or double complex) values(maxcols) output
609: .ve
610: Where maxcols >= maximum nonzeros in any row of the matrix.
612: In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
613: before another call to `MatGetRow()` can be made.
615: Level: advanced
617: .seealso: `MatGetRow()`
618: @*/
619: PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
620: {
624: if (!mat->ops->restorerow) return 0;
625: (*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
626: if (ncols) *ncols = 0;
627: if (cols) *cols = NULL;
628: if (vals) *vals = NULL;
629: return 0;
630: }
632: /*@
633: MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
634: You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
636: Not Collective
638: Input Parameters:
639: . mat - the matrix
641: Note:
642: 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.
644: Level: advanced
646: .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
647: @*/
648: PetscErrorCode MatGetRowUpperTriangular(Mat mat)
649: {
654: MatCheckPreallocated(mat, 1);
655: if (!mat->ops->getrowuppertriangular) return 0;
656: PetscUseTypeMethod(mat, getrowuppertriangular);
657: return 0;
658: }
660: /*@
661: MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
663: Not Collective
665: Input Parameters:
666: . mat - the matrix
668: Note:
669: This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
671: Level: advanced
673: .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()`
674: @*/
675: PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
676: {
681: MatCheckPreallocated(mat, 1);
682: if (!mat->ops->restorerowuppertriangular) return 0;
683: PetscUseTypeMethod(mat, restorerowuppertriangular);
684: return 0;
685: }
687: /*@C
688: MatSetOptionsPrefix - Sets the prefix used for searching for all
689: `Mat` options in the database.
691: Logically Collective on A
693: Input Parameters:
694: + A - the matrix
695: - prefix - the prefix to prepend to all option names
697: Notes:
698: A hyphen (-) must NOT be given at the beginning of the prefix name.
699: The first character of all runtime options is AUTOMATICALLY the hyphen.
701: This is NOT used for options for the factorization of the matrix. Normally the
702: prefix is automatically passed in from the PC calling the factorization. To set
703: it directly use `MatSetOptionsPrefixFactor()`
705: Level: advanced
707: .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
708: @*/
709: PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
710: {
712: PetscObjectSetOptionsPrefix((PetscObject)A, prefix);
713: return 0;
714: }
716: /*@C
717: MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
718: for matrices created with `MatGetFactor()`
720: Logically Collective on A
722: Input Parameters:
723: + A - the matrix
724: - prefix - the prefix to prepend to all option names for the factored matrix
726: Notes:
727: A hyphen (-) must NOT be given at the beginning of the prefix name.
728: The first character of all runtime options is AUTOMATICALLY the hyphen.
730: Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
731: it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()`
733: Level: developer
735: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
736: @*/
737: PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
738: {
740: if (prefix) {
743: if (prefix != A->factorprefix) {
744: PetscFree(A->factorprefix);
745: PetscStrallocpy(prefix, &A->factorprefix);
746: }
747: } else PetscFree(A->factorprefix);
748: return 0;
749: }
751: /*@C
752: MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
753: for matrices created with `MatGetFactor()`
755: Logically Collective on A
757: Input Parameters:
758: + A - the matrix
759: - prefix - the prefix to prepend to all option names for the factored matrix
761: Notes:
762: A hyphen (-) must NOT be given at the beginning of the prefix name.
763: The first character of all runtime options is AUTOMATICALLY the hyphen.
765: Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
766: it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()`
768: Level: developer
770: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
771: `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
772: `MatSetOptionsPrefix()`
773: @*/
774: PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
775: {
776: char *buf = A->factorprefix;
777: size_t len1, len2;
780: if (!prefix) return 0;
781: if (!buf) {
782: MatSetOptionsPrefixFactor(A, prefix);
783: return 0;
784: }
787: PetscStrlen(prefix, &len1);
788: PetscStrlen(buf, &len2);
789: PetscMalloc1(1 + len1 + len2, &A->factorprefix);
790: PetscStrcpy(A->factorprefix, buf);
791: PetscStrcat(A->factorprefix, prefix);
792: PetscFree(buf);
793: return 0;
794: }
796: /*@C
797: MatAppendOptionsPrefix - Appends to the prefix used for searching for all
798: matrix options in the database.
800: Logically Collective on A
802: Input Parameters:
803: + A - the matrix
804: - prefix - the prefix to prepend to all option names
806: Note:
807: A hyphen (-) must NOT be given at the beginning of the prefix name.
808: The first character of all runtime options is AUTOMATICALLY the hyphen.
810: Level: advanced
812: .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
813: @*/
814: PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
815: {
817: PetscObjectAppendOptionsPrefix((PetscObject)A, prefix);
818: return 0;
819: }
821: /*@C
822: MatGetOptionsPrefix - Gets the prefix used for searching for all
823: matrix options in the database.
825: Not Collective
827: Input Parameter:
828: . A - the matrix
830: Output Parameter:
831: . prefix - pointer to the prefix string used
833: Fortran Note:
834: On the fortran side, the user should pass in a string 'prefix' of
835: sufficient length to hold the prefix.
837: Level: advanced
839: .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
840: @*/
841: PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
842: {
845: PetscObjectGetOptionsPrefix((PetscObject)A, prefix);
846: return 0;
847: }
849: /*@
850: MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
852: Collective on A
854: Input Parameters:
855: . A - the matrix
857: Notes:
858: The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
860: Users can reset the preallocation to access the original memory.
862: Currently only supported for `MATMPIAIJ` and `MATSEQAIJ` matrices.
864: Level: beginner
866: .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
867: @*/
868: PetscErrorCode MatResetPreallocation(Mat A)
869: {
872: PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
873: return 0;
874: }
876: /*@
877: MatSetUp - Sets up the internal matrix data structures for later use.
879: Collective on A
881: Input Parameters:
882: . A - the matrix
884: Notes:
885: If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
887: If a suitable preallocation routine is used, this function does not need to be called.
889: See the Performance chapter of the PETSc users manual for how to preallocate matrices
891: This routine is called internally by other matrix functions when needed so rarely needs to be called by users
893: Level: intermediate
895: .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
896: @*/
897: PetscErrorCode MatSetUp(Mat A)
898: {
900: if (!((PetscObject)A)->type_name) {
901: PetscMPIInt size;
903: MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);
904: MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ);
905: }
906: if (!A->preallocated && A->ops->setup) {
907: PetscInfo(A, "Warning not preallocating matrix storage\n");
908: PetscUseTypeMethod(A, setup);
909: }
910: PetscLayoutSetUp(A->rmap);
911: PetscLayoutSetUp(A->cmap);
912: A->preallocated = PETSC_TRUE;
913: return 0;
914: }
916: #if defined(PETSC_HAVE_SAWS)
917: #include <petscviewersaws.h>
918: #endif
920: /*@C
921: MatViewFromOptions - View properties of the matrix from the options database
923: Collective on A
925: Input Parameters:
926: + A - the matrix
927: . obj - optional additional object that provides the options prefix to use
928: - name - command line option
930: Options Database:
931: . -mat_view [viewertype]:... - the viewer and its options
933: Notes:
934: .vb
935: If no value is provided ascii:stdout is used
936: ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
937: for example ascii::ascii_info prints just the information about the object not all details
938: unless :append is given filename opens in write mode, overwriting what was already there
939: binary[:[filename][:[format][:append]]] defaults to the file binaryoutput
940: draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x
941: socket[:port] defaults to the standard output port
942: saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs)
943: .ve
945: Level: intermediate
947: .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
948: @*/
949: PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
950: {
952: PetscObjectViewFromOptions((PetscObject)A, obj, name);
953: return 0;
954: }
956: /*@C
957: MatView - display information about a matrix in a variety ways
959: Collective on mat
961: Input Parameters:
962: + mat - the matrix
963: - viewer - visualization context
965: Notes:
966: The available visualization contexts include
967: + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
968: . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
969: . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
970: - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
972: The user can open alternative visualization contexts with
973: + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
974: . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
975: specified file; corresponding input uses MatLoad()
976: . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
977: an X window display
978: - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
979: Currently only the sequential dense and AIJ
980: matrix types support the Socket viewer.
982: The user can call `PetscViewerPushFormat()` to specify the output
983: format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
984: `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include
985: + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
986: . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
987: . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
988: . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
989: format common among all matrix types
990: . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
991: format (which is in many cases the same as the default)
992: . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
993: size and structure (not the matrix entries)
994: - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
995: the matrix structure
997: Options Database Keys:
998: + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
999: . -mat_view ::ascii_info_detail - Prints more detailed info
1000: . -mat_view - Prints matrix in ASCII format
1001: . -mat_view ::ascii_matlab - Prints matrix in Matlab format
1002: . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1003: . -display <name> - Sets display name (default is host)
1004: . -draw_pause <sec> - Sets number of seconds to pause after display
1005: . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1006: . -viewer_socket_machine <machine> -
1007: . -viewer_socket_port <port> -
1008: . -mat_view binary - save matrix to file in binary format
1009: - -viewer_binary_filename <name> -
1011: Level: beginner
1013: Notes:
1014: The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1015: the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1017: In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1019: See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1020: viewer is used.
1022: See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1023: viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1025: One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1026: and then use the following mouse functions.
1027: .vb
1028: left mouse: zoom in
1029: middle mouse: zoom out
1030: right mouse: continue with the simulation
1031: .ve
1033: .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`,
1034: `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1035: @*/
1036: PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1037: {
1038: PetscInt rows, cols, rbs, cbs;
1039: PetscBool isascii, isstring, issaws;
1040: PetscViewerFormat format;
1041: PetscMPIInt size;
1045: if (!viewer) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer);
1048: MatCheckPreallocated(mat, 1);
1050: PetscViewerGetFormat(viewer, &format);
1051: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
1052: if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) return 0;
1054: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring);
1055: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
1056: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws);
1059: PetscLogEventBegin(MAT_View, mat, viewer, 0, 0);
1060: if (isascii) {
1062: PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer);
1063: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1064: MatNullSpace nullsp, transnullsp;
1066: PetscViewerASCIIPushTab(viewer);
1067: MatGetSize(mat, &rows, &cols);
1068: MatGetBlockSizes(mat, &rbs, &cbs);
1069: if (rbs != 1 || cbs != 1) {
1070: if (rbs != cbs) PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs);
1071: else PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs);
1072: } else PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols);
1073: if (mat->factortype) {
1074: MatSolverType solver;
1075: MatFactorGetSolverType(mat, &solver);
1076: PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver);
1077: }
1078: if (mat->ops->getinfo) {
1079: MatInfo info;
1080: MatGetInfo(mat, MAT_GLOBAL_SUM, &info);
1081: PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated);
1082: if (!mat->factortype) PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs);
1083: }
1084: MatGetNullSpace(mat, &nullsp);
1085: MatGetTransposeNullSpace(mat, &transnullsp);
1086: if (nullsp) PetscViewerASCIIPrintf(viewer, " has attached null space\n");
1087: if (transnullsp && transnullsp != nullsp) PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n");
1088: MatGetNearNullSpace(mat, &nullsp);
1089: if (nullsp) PetscViewerASCIIPrintf(viewer, " has attached near null space\n");
1090: PetscViewerASCIIPushTab(viewer);
1091: MatProductView(mat, viewer);
1092: PetscViewerASCIIPopTab(viewer);
1093: }
1094: } else if (issaws) {
1095: #if defined(PETSC_HAVE_SAWS)
1096: PetscMPIInt rank;
1098: PetscObjectName((PetscObject)mat);
1099: MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1100: if (!((PetscObject)mat)->amsmem && rank == 0) PetscObjectViewSAWs((PetscObject)mat, viewer);
1101: #endif
1102: } else if (isstring) {
1103: const char *type;
1104: MatGetType(mat, &type);
1105: PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type);
1106: PetscTryTypeMethod(mat, view, viewer);
1107: }
1108: if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1109: PetscViewerASCIIPushTab(viewer);
1110: PetscUseTypeMethod(mat, viewnative, viewer);
1111: PetscViewerASCIIPopTab(viewer);
1112: } else if (mat->ops->view) {
1113: PetscViewerASCIIPushTab(viewer);
1114: PetscUseTypeMethod(mat, view, viewer);
1115: PetscViewerASCIIPopTab(viewer);
1116: }
1117: if (isascii) {
1118: PetscViewerGetFormat(viewer, &format);
1119: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscViewerASCIIPopTab(viewer);
1120: }
1121: PetscLogEventEnd(MAT_View, mat, viewer, 0, 0);
1122: return 0;
1123: }
1125: #if defined(PETSC_USE_DEBUG)
1126: #include <../src/sys/totalview/tv_data_display.h>
1127: PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1128: {
1129: TV_add_row("Local rows", "int", &mat->rmap->n);
1130: TV_add_row("Local columns", "int", &mat->cmap->n);
1131: TV_add_row("Global rows", "int", &mat->rmap->N);
1132: TV_add_row("Global columns", "int", &mat->cmap->N);
1133: TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1134: return TV_format_OK;
1135: }
1136: #endif
1138: /*@C
1139: MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1140: with `MatView()`. The matrix format is determined from the options database.
1141: Generates a parallel MPI matrix if the communicator has more than one
1142: processor. The default matrix type is `MATAIJ`.
1144: Collective on mat
1146: Input Parameters:
1147: + mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1148: or some related function before a call to `MatLoad()`
1149: - viewer - binary/HDF5 file viewer
1151: Options Database Keys:
1152: Used with block matrix formats (`MATSEQBAIJ`, ...) to specify
1153: block size
1154: . -matload_block_size <bs> - set block size
1156: Level: beginner
1158: Notes:
1159: If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1160: `Mat` before calling this routine if you wish to set it from the options database.
1162: `MatLoad()` automatically loads into the options database any options
1163: given in the file filename.info where filename is the name of the file
1164: that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1165: file will be ignored if you use the -viewer_binary_skip_info option.
1167: If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1168: sets the default matrix type AIJ and sets the local and global sizes.
1169: If type and/or size is already set, then the same are used.
1171: In parallel, each processor can load a subset of rows (or the
1172: entire matrix). This routine is especially useful when a large
1173: matrix is stored on disk and only part of it is desired on each
1174: processor. For example, a parallel solver may access only some of
1175: the rows from each processor. The algorithm used here reads
1176: relatively small blocks of data rather than reading the entire
1177: matrix and then subsetting it.
1179: Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1180: Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1181: or the sequence like
1182: .vb
1183: `PetscViewer` v;
1184: `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1185: `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1186: `PetscViewerSetFromOptions`(v);
1187: `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1188: `PetscViewerFileSetName`(v,"datafile");
1189: .ve
1190: The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1191: $ -viewer_type {binary,hdf5}
1193: See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1194: and src/mat/tutorials/ex10.c with the second approach.
1196: Notes about the PETSc binary format:
1197: In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1198: is read onto rank 0 and then shipped to its destination rank, one after another.
1199: Multiple objects, both matrices and vectors, can be stored within the same file.
1200: Their PetscObject name is ignored; they are loaded in the order of their storage.
1202: Most users should not need to know the details of the binary storage
1203: format, since `MatLoad()` and `MatView()` completely hide these details.
1204: But for anyone who's interested, the standard binary matrix storage
1205: format is
1207: $ PetscInt MAT_FILE_CLASSID
1208: $ PetscInt number of rows
1209: $ PetscInt number of columns
1210: $ PetscInt total number of nonzeros
1211: $ PetscInt *number nonzeros in each row
1212: $ PetscInt *column indices of all nonzeros (starting index is zero)
1213: $ PetscScalar *values of all nonzeros
1215: PETSc automatically does the byte swapping for
1216: machines that store the bytes reversed, e.g. DEC alpha, freebsd,
1217: Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1218: read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1219: and `PetscBinaryWrite()` to see how this may be done.
1221: Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1222: In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1223: Each processor's chunk is loaded independently by its owning rank.
1224: Multiple objects, both matrices and vectors, can be stored within the same file.
1225: They are looked up by their PetscObject name.
1227: As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1228: by default the same structure and naming of the AIJ arrays and column count
1229: within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1230: $ save example.mat A b -v7.3
1231: can be directly read by this routine (see Reference 1 for details).
1232: Note that depending on your MATLAB version, this format might be a default,
1233: otherwise you can set it as default in Preferences.
1235: Unless -nocompression flag is used to save the file in MATLAB,
1236: PETSc must be configured with ZLIB package.
1238: See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1240: Current HDF5 (MAT-File) limitations:
1241: This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1243: Corresponding `MatView()` is not yet implemented.
1245: The loaded matrix is actually a transpose of the original one in MATLAB,
1246: unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1247: With this format, matrix is automatically transposed by PETSc,
1248: unless the matrix is marked as SPD or symmetric
1249: (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1251: References:
1252: . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1254: .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1255: @*/
1256: PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1257: {
1258: PetscBool flg;
1263: if (!((PetscObject)mat)->type_name) MatSetType(mat, MATAIJ);
1265: flg = PETSC_FALSE;
1266: PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL);
1267: if (flg) {
1268: MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE);
1269: MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE);
1270: }
1271: flg = PETSC_FALSE;
1272: PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL);
1273: if (flg) MatSetOption(mat, MAT_SPD, PETSC_TRUE);
1275: PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0);
1276: PetscUseTypeMethod(mat, load, viewer);
1277: PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0);
1278: return 0;
1279: }
1281: static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1282: {
1283: Mat_Redundant *redund = *redundant;
1285: if (redund) {
1286: if (redund->matseq) { /* via MatCreateSubMatrices() */
1287: ISDestroy(&redund->isrow);
1288: ISDestroy(&redund->iscol);
1289: MatDestroySubMatrices(1, &redund->matseq);
1290: } else {
1291: PetscFree2(redund->send_rank, redund->recv_rank);
1292: PetscFree(redund->sbuf_j);
1293: PetscFree(redund->sbuf_a);
1294: for (PetscInt i = 0; i < redund->nrecvs; i++) {
1295: PetscFree(redund->rbuf_j[i]);
1296: PetscFree(redund->rbuf_a[i]);
1297: }
1298: PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a);
1299: }
1301: if (redund->subcomm) PetscCommDestroy(&redund->subcomm);
1302: PetscFree(redund);
1303: }
1304: return 0;
1305: }
1307: /*@C
1308: MatDestroy - Frees space taken by a matrix.
1310: Collective on A
1312: Input Parameter:
1313: . A - the matrix
1315: Level: beginner
1317: Developer Note:
1318: Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1319: `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1320: `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1321: if changes are needed here.
1323: .seealso: `Mat`, `MatCreate()`
1324: @*/
1325: PetscErrorCode MatDestroy(Mat *A)
1326: {
1327: if (!*A) return 0;
1329: if (--((PetscObject)(*A))->refct > 0) {
1330: *A = NULL;
1331: return 0;
1332: }
1334: /* if memory was published with SAWs then destroy it */
1335: PetscObjectSAWsViewOff((PetscObject)*A);
1336: PetscTryTypeMethod((*A), destroy);
1338: PetscFree((*A)->factorprefix);
1339: PetscFree((*A)->defaultvectype);
1340: PetscFree((*A)->defaultrandtype);
1341: PetscFree((*A)->bsizes);
1342: PetscFree((*A)->solvertype);
1343: for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscFree((*A)->preferredordering[i]);
1344: if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1345: MatDestroy_Redundant(&(*A)->redundant);
1346: MatProductClear(*A);
1347: MatNullSpaceDestroy(&(*A)->nullsp);
1348: MatNullSpaceDestroy(&(*A)->transnullsp);
1349: MatNullSpaceDestroy(&(*A)->nearnullsp);
1350: MatDestroy(&(*A)->schur);
1351: PetscLayoutDestroy(&(*A)->rmap);
1352: PetscLayoutDestroy(&(*A)->cmap);
1353: PetscHeaderDestroy(A);
1354: return 0;
1355: }
1357: /*@C
1358: MatSetValues - Inserts or adds a block of values into a matrix.
1359: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1360: MUST be called after all calls to `MatSetValues()` have been completed.
1362: Not Collective
1364: Input Parameters:
1365: + mat - the matrix
1366: . v - a logically two-dimensional array of values
1367: . m, idxm - the number of rows and their global indices
1368: . n, idxn - the number of columns and their global indices
1369: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1371: Notes:
1372: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1373: `MatSetUp()` before using this routine
1375: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1377: Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1378: options cannot be mixed without intervening calls to the assembly
1379: routines.
1381: `MatSetValues()` uses 0-based row and column numbers in Fortran
1382: as well as in C.
1384: Negative indices may be passed in idxm and idxn, these rows and columns are
1385: simply ignored. This allows easily inserting element stiffness matrices
1386: with homogeneous Dirchlet boundary conditions that you don't want represented
1387: in the matrix.
1389: Efficiency Alert:
1390: The routine `MatSetValuesBlocked()` may offer much better efficiency
1391: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1393: Level: beginner
1395: Developer Note:
1396: This is labeled with C so does not automatically generate Fortran stubs and interfaces
1397: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1399: .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1400: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1401: @*/
1402: PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1403: {
1407: if (!m || !n) return 0; /* no values to insert */
1410: MatCheckPreallocated(mat, 1);
1412: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1415: if (PetscDefined(USE_DEBUG)) {
1416: PetscInt i, j;
1419: for (i = 0; i < m; i++) {
1420: for (j = 0; j < n; j++) {
1421: if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1422: #if defined(PETSC_USE_COMPLEX)
1423: 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]);
1424: #else
1425: 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]);
1426: #endif
1427: }
1428: }
1431: }
1433: if (mat->assembled) {
1434: mat->was_assembled = PETSC_TRUE;
1435: mat->assembled = PETSC_FALSE;
1436: }
1437: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1438: PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1439: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1440: return 0;
1441: }
1443: /*@C
1444: MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1445: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1446: MUST be called after all calls to `MatSetValues()` have been completed.
1448: Not Collective
1450: Input Parameters:
1451: + mat - the matrix
1452: . v - a logically two-dimensional array of values
1453: . ism - the rows to provide
1454: . isn - the columns to provide
1455: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1457: Notes:
1458: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1459: `MatSetUp()` before using this routine
1461: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1463: Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1464: options cannot be mixed without intervening calls to the assembly
1465: routines.
1467: MatSetValues() uses 0-based row and column numbers in Fortran
1468: as well as in C.
1470: Negative indices may be passed in ism and isn, these rows and columns are
1471: simply ignored. This allows easily inserting element stiffness matrices
1472: with homogeneous Dirchlet boundary conditions that you don't want represented
1473: in the matrix.
1475: Efficiency Alert:
1476: The routine `MatSetValuesBlocked()` may offer much better efficiency
1477: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1479: Level: beginner
1481: Developer Notes:
1482: This is labeled with C so does not automatically generate Fortran stubs and interfaces
1483: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1485: This is currently not optimized for any particular `ISType`
1487: .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1488: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1489: @*/
1490: PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1491: {
1492: PetscInt m, n;
1493: const PetscInt *rows, *cols;
1497: ISGetIndices(ism, &rows);
1498: ISGetIndices(isn, &cols);
1499: ISGetLocalSize(ism, &m);
1500: ISGetLocalSize(isn, &n);
1501: MatSetValues(mat, m, rows, n, cols, v, addv);
1502: ISRestoreIndices(ism, &rows);
1503: ISRestoreIndices(isn, &cols);
1504: return 0;
1505: }
1507: /*@
1508: MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1509: values into a matrix
1511: Not Collective
1513: Input Parameters:
1514: + mat - the matrix
1515: . row - the (block) row to set
1516: - v - a logically two-dimensional array of values
1518: Notes:
1519: By the values, v, are column-oriented (for the block version) and sorted
1521: All the nonzeros in the row must be provided
1523: The matrix must have previously had its column indices set
1525: The row must belong to this process
1527: Level: intermediate
1529: .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1530: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1531: @*/
1532: PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1533: {
1534: PetscInt globalrow;
1539: ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow);
1540: MatSetValuesRow(mat, globalrow, v);
1541: return 0;
1542: }
1544: /*@
1545: MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1546: values into a matrix
1548: Not Collective
1550: Input Parameters:
1551: + mat - the matrix
1552: . row - the (block) row to set
1553: - 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
1555: Notes:
1556: The values, v, are column-oriented for the block version.
1558: All the nonzeros in the row must be provided
1560: THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1562: The row must belong to this process
1564: Level: advanced
1566: .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1567: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1568: @*/
1569: PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1570: {
1574: MatCheckPreallocated(mat, 1);
1578: mat->insertmode = INSERT_VALUES;
1580: if (mat->assembled) {
1581: mat->was_assembled = PETSC_TRUE;
1582: mat->assembled = PETSC_FALSE;
1583: }
1584: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1585: PetscUseTypeMethod(mat, setvaluesrow, row, v);
1586: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1587: return 0;
1588: }
1590: /*@
1591: MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1592: Using structured grid indexing
1594: Not Collective
1596: Input Parameters:
1597: + mat - the matrix
1598: . m - number of rows being entered
1599: . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1600: . n - number of columns being entered
1601: . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1602: . v - a logically two-dimensional array of values
1603: - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1605: Notes:
1606: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1608: Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1609: options cannot be mixed without intervening calls to the assembly
1610: routines.
1612: The grid coordinates are across the entire grid, not just the local portion
1614: `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1615: as well as in C.
1617: For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1619: In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1620: or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1622: The columns and rows in the stencil passed in MUST be contained within the
1623: ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1624: if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1625: local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1626: first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1628: In Fortran idxm and idxn should be declared as
1629: $ MatStencil idxm(4,m),idxn(4,n)
1630: and the values inserted using
1631: $ idxm(MatStencil_i,1) = i
1632: $ idxm(MatStencil_j,1) = j
1633: $ idxm(MatStencil_k,1) = k
1634: $ idxm(MatStencil_c,1) = c
1635: etc
1637: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1638: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1639: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1640: `DM_BOUNDARY_PERIODIC` boundary type.
1642: 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
1643: a single value per point) you can skip filling those indices.
1645: Inspired by the structured grid interface to the HYPRE package
1646: (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1648: Efficiency Alert:
1649: The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1650: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1652: Level: beginner
1654: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1655: `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1656: @*/
1657: PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1658: {
1659: PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1660: PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1661: PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1663: if (!m || !n) return 0; /* no values to insert */
1669: if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1670: jdxm = buf;
1671: jdxn = buf + m;
1672: } else {
1673: PetscMalloc2(m, &bufm, n, &bufn);
1674: jdxm = bufm;
1675: jdxn = bufn;
1676: }
1677: for (i = 0; i < m; i++) {
1678: for (j = 0; j < 3 - sdim; j++) dxm++;
1679: tmp = *dxm++ - starts[0];
1680: for (j = 0; j < dim - 1; j++) {
1681: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1682: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1683: }
1684: if (mat->stencil.noc) dxm++;
1685: jdxm[i] = tmp;
1686: }
1687: for (i = 0; i < n; i++) {
1688: for (j = 0; j < 3 - sdim; j++) dxn++;
1689: tmp = *dxn++ - starts[0];
1690: for (j = 0; j < dim - 1; j++) {
1691: if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1692: else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1693: }
1694: if (mat->stencil.noc) dxn++;
1695: jdxn[i] = tmp;
1696: }
1697: MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv);
1698: PetscFree2(bufm, bufn);
1699: return 0;
1700: }
1702: /*@
1703: MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1704: Using structured grid indexing
1706: Not Collective
1708: Input Parameters:
1709: + mat - the matrix
1710: . m - number of rows being entered
1711: . idxm - grid coordinates for matrix rows being entered
1712: . n - number of columns being entered
1713: . idxn - grid coordinates for matrix columns being entered
1714: . v - a logically two-dimensional array of values
1715: - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1717: Notes:
1718: By default the values, v, are row-oriented and unsorted.
1719: See `MatSetOption()` for other options.
1721: Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1722: options cannot be mixed without intervening calls to the assembly
1723: routines.
1725: The grid coordinates are across the entire grid, not just the local portion
1727: `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1728: as well as in C.
1730: For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1732: In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1733: or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1735: The columns and rows in the stencil passed in MUST be contained within the
1736: ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1737: if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1738: local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1739: first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1741: In Fortran idxm and idxn should be declared as
1742: $ MatStencil idxm(4,m),idxn(4,n)
1743: and the values inserted using
1744: $ idxm(MatStencil_i,1) = i
1745: $ idxm(MatStencil_j,1) = j
1746: $ idxm(MatStencil_k,1) = k
1747: etc
1749: Negative indices may be passed in idxm and idxn, these rows and columns are
1750: simply ignored. This allows easily inserting element stiffness matrices
1751: with homogeneous Dirchlet boundary conditions that you don't want represented
1752: in the matrix.
1754: Inspired by the structured grid interface to the HYPRE package
1755: (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1757: Level: beginner
1759: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1760: `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1761: `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1762: @*/
1763: PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1764: {
1765: PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1766: PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1767: PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1769: if (!m || !n) return 0; /* no values to insert */
1776: if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1777: jdxm = buf;
1778: jdxn = buf + m;
1779: } else {
1780: PetscMalloc2(m, &bufm, n, &bufn);
1781: jdxm = bufm;
1782: jdxn = bufn;
1783: }
1784: for (i = 0; i < m; i++) {
1785: for (j = 0; j < 3 - sdim; j++) dxm++;
1786: tmp = *dxm++ - starts[0];
1787: for (j = 0; j < sdim - 1; j++) {
1788: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1789: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1790: }
1791: dxm++;
1792: jdxm[i] = tmp;
1793: }
1794: for (i = 0; i < n; i++) {
1795: for (j = 0; j < 3 - sdim; j++) dxn++;
1796: tmp = *dxn++ - starts[0];
1797: for (j = 0; j < sdim - 1; j++) {
1798: if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1799: else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1800: }
1801: dxn++;
1802: jdxn[i] = tmp;
1803: }
1804: MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv);
1805: PetscFree2(bufm, bufn);
1806: return 0;
1807: }
1809: /*@
1810: MatSetStencil - Sets the grid information for setting values into a matrix via
1811: `MatSetValuesStencil()`
1813: Not Collective
1815: Input Parameters:
1816: + mat - the matrix
1817: . dim - dimension of the grid 1, 2, or 3
1818: . dims - number of grid points in x, y, and z direction, including ghost points on your processor
1819: . starts - starting point of ghost nodes on your processor in x, y, and z direction
1820: - dof - number of degrees of freedom per node
1822: Notes:
1823: Inspired by the structured grid interface to the HYPRE package
1824: (www.llnl.gov/CASC/hyper)
1826: For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1827: user.
1829: Level: beginner
1831: .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1832: `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1833: @*/
1834: PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1835: {
1840: mat->stencil.dim = dim + (dof > 1);
1841: for (PetscInt i = 0; i < dim; i++) {
1842: mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */
1843: mat->stencil.starts[i] = starts[dim - i - 1];
1844: }
1845: mat->stencil.dims[dim] = dof;
1846: mat->stencil.starts[dim] = 0;
1847: mat->stencil.noc = (PetscBool)(dof == 1);
1848: return 0;
1849: }
1851: /*@C
1852: MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1854: Not Collective
1856: Input Parameters:
1857: + mat - the matrix
1858: . v - a logically two-dimensional array of values
1859: . m, idxm - the number of block rows and their global block indices
1860: . n, idxn - the number of block columns and their global block indices
1861: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1863: Notes:
1864: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1865: MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1867: The m and n count the NUMBER of blocks in the row direction and column direction,
1868: NOT the total number of rows/columns; for example, if the block size is 2 and
1869: you are passing in values for rows 2,3,4,5 then m would be 2 (not 4).
1870: The values in idxm would be 1 2; that is the first index for each block divided by
1871: the block size.
1873: Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1874: preallocating it).
1876: By default the values, v, are row-oriented, so the layout of
1877: v is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1879: Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1880: options cannot be mixed without intervening calls to the assembly
1881: routines.
1883: `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1884: as well as in C.
1886: Negative indices may be passed in idxm and idxn, these rows and columns are
1887: simply ignored. This allows easily inserting element stiffness matrices
1888: with homogeneous Dirchlet boundary conditions that you don't want represented
1889: in the matrix.
1891: Each time an entry is set within a sparse matrix via `MatSetValues()`,
1892: internal searching must be done to determine where to place the
1893: data in the matrix storage space. By instead inserting blocks of
1894: entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1895: reduced.
1897: Example:
1898: $ Suppose m=n=2 and block size(bs) = 2 The array is
1899: $
1900: $ 1 2 | 3 4
1901: $ 5 6 | 7 8
1902: $ - - - | - - -
1903: $ 9 10 | 11 12
1904: $ 13 14 | 15 16
1905: $
1906: $ v[] should be passed in like
1907: $ v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1908: $
1909: $ If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1910: $ v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1912: Level: intermediate
1914: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1915: @*/
1916: PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1917: {
1921: if (!m || !n) return 0; /* no values to insert */
1924: MatCheckPreallocated(mat, 1);
1925: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1927: if (PetscDefined(USE_DEBUG)) {
1930: }
1931: if (PetscDefined(USE_DEBUG)) {
1932: PetscInt rbs, cbs, M, N, i;
1933: MatGetBlockSizes(mat, &rbs, &cbs);
1934: MatGetSize(mat, &M, &N);
1937: }
1938: if (mat->assembled) {
1939: mat->was_assembled = PETSC_TRUE;
1940: mat->assembled = PETSC_FALSE;
1941: }
1942: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1943: if (mat->ops->setvaluesblocked) {
1944: PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1945: } else {
1946: PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1947: PetscInt i, j, bs, cbs;
1949: MatGetBlockSizes(mat, &bs, &cbs);
1950: if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1951: iidxm = buf;
1952: iidxn = buf + m * bs;
1953: } else {
1954: PetscMalloc2(m * bs, &bufr, n * cbs, &bufc);
1955: iidxm = bufr;
1956: iidxn = bufc;
1957: }
1958: for (i = 0; i < m; i++) {
1959: for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
1960: }
1961: if (m != n || bs != cbs || idxm != idxn) {
1962: for (i = 0; i < n; i++) {
1963: for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
1964: }
1965: } else iidxn = iidxm;
1966: MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv);
1967: PetscFree2(bufr, bufc);
1968: }
1969: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1970: return 0;
1971: }
1973: /*@C
1974: MatGetValues - Gets a block of local values from a matrix.
1976: Not Collective; can only return values that are owned by the give process
1978: Input Parameters:
1979: + mat - the matrix
1980: . v - a logically two-dimensional array for storing the values
1981: . m, idxm - the number of rows and their global indices
1982: - n, idxn - the number of columns and their global indices
1984: Notes:
1985: The user must allocate space (m*n `PetscScalar`s) for the values, v.
1986: The values, v, are then returned in a row-oriented format,
1987: analogous to that used by default in `MatSetValues()`.
1989: `MatGetValues()` uses 0-based row and column numbers in
1990: Fortran as well as in C.
1992: `MatGetValues()` requires that the matrix has been assembled
1993: with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to
1994: `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
1995: without intermediate matrix assembly.
1997: Negative row or column indices will be ignored and those locations in v[] will be
1998: left unchanged.
2000: For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2001: That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2002: from `MatGetOwnershipRange`(mat,&rstart,&rend).
2004: Level: advanced
2006: .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2007: @*/
2008: PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2009: {
2012: if (!m || !n) return 0;
2018: MatCheckPreallocated(mat, 1);
2020: PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2021: PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2022: PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2023: return 0;
2024: }
2026: /*@C
2027: MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2028: defined previously by `MatSetLocalToGlobalMapping()`
2030: Not Collective
2032: Input Parameters:
2033: + mat - the matrix
2034: . nrow, irow - number of rows and their local indices
2035: - ncol, icol - number of columns and their local indices
2037: Output Parameter:
2038: . y - a logically two-dimensional array of values
2040: Notes:
2041: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2043: This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2044: are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2045: determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2046: with `MatSetLocalToGlobalMapping()`.
2048: Developer Note:
2049: This is labelled with C so does not automatically generate Fortran stubs and interfaces
2050: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2052: Level: advanced
2054: .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2055: `MatSetValuesLocal()`, `MatGetValues()`
2056: @*/
2057: PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2058: {
2062: MatCheckPreallocated(mat, 1);
2063: if (!nrow || !ncol) return 0; /* no values to retrieve */
2066: if (PetscDefined(USE_DEBUG)) {
2069: }
2071: PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2072: if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2073: else {
2074: PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2075: if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2076: irowm = buf;
2077: icolm = buf + nrow;
2078: } else {
2079: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2080: irowm = bufr;
2081: icolm = bufc;
2082: }
2085: ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm);
2086: ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm);
2087: MatGetValues(mat, nrow, irowm, ncol, icolm, y);
2088: PetscFree2(bufr, bufc);
2089: }
2090: PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2091: return 0;
2092: }
2094: /*@
2095: MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2096: the same size. Currently, this can only be called once and creates the given matrix.
2098: Not Collective
2100: Input Parameters:
2101: + mat - the matrix
2102: . nb - the number of blocks
2103: . bs - the number of rows (and columns) in each block
2104: . rows - a concatenation of the rows for each block
2105: - v - a concatenation of logically two-dimensional arrays of values
2107: Note:
2108: `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2110: In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2112: Level: advanced
2114: .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2115: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2116: @*/
2117: PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2118: {
2123: PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2125: PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0);
2126: if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2127: else {
2128: for (PetscInt b = 0; b < nb; ++b) MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES);
2129: }
2130: PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0);
2131: return 0;
2132: }
2134: /*@
2135: MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2136: the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2137: using a local (per-processor) numbering.
2139: Not Collective
2141: Input Parameters:
2142: + x - the matrix
2143: . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2144: - cmapping - column mapping
2146: Level: intermediate
2148: Note:
2149: If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2151: .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2152: @*/
2153: PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2154: {
2159: if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2160: else {
2161: PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping);
2162: PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping);
2163: }
2164: return 0;
2165: }
2167: /*@
2168: MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2170: Not Collective
2172: Input Parameter:
2173: . A - the matrix
2175: Output Parameters:
2176: + rmapping - row mapping
2177: - cmapping - column mapping
2179: Level: advanced
2181: .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2182: @*/
2183: PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2184: {
2187: if (rmapping) {
2189: *rmapping = A->rmap->mapping;
2190: }
2191: if (cmapping) {
2193: *cmapping = A->cmap->mapping;
2194: }
2195: return 0;
2196: }
2198: /*@
2199: MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2201: Logically Collective on A
2203: Input Parameters:
2204: + A - the matrix
2205: . rmap - row layout
2206: - cmap - column layout
2208: Level: advanced
2210: Note:
2211: The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2213: .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2214: @*/
2215: PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2216: {
2218: PetscLayoutReference(rmap, &A->rmap);
2219: PetscLayoutReference(cmap, &A->cmap);
2220: return 0;
2221: }
2223: /*@
2224: MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2226: Not Collective
2228: Input Parameter:
2229: . A - the matrix
2231: Output Parameters:
2232: + rmap - row layout
2233: - cmap - column layout
2235: Level: advanced
2237: .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2238: @*/
2239: PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2240: {
2243: if (rmap) {
2245: *rmap = A->rmap;
2246: }
2247: if (cmap) {
2249: *cmap = A->cmap;
2250: }
2251: return 0;
2252: }
2254: /*@C
2255: MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2256: using a local numbering of the nodes.
2258: Not Collective
2260: Input Parameters:
2261: + mat - the matrix
2262: . nrow, irow - number of rows and their local indices
2263: . ncol, icol - number of columns and their local indices
2264: . y - a logically two-dimensional array of values
2265: - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2267: Notes:
2268: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2269: `MatSetUp()` before using this routine
2271: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2273: Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2274: options cannot be mixed without intervening calls to the assembly
2275: routines.
2277: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2278: MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2280: Level: intermediate
2282: Developer Note:
2283: This is labeled with C so does not automatically generate Fortran stubs and interfaces
2284: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2286: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2287: `MatGetValuesLocal()`
2288: @*/
2289: PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2290: {
2294: MatCheckPreallocated(mat, 1);
2295: if (!nrow || !ncol) return 0; /* no values to insert */
2298: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2300: if (PetscDefined(USE_DEBUG)) {
2303: }
2305: if (mat->assembled) {
2306: mat->was_assembled = PETSC_TRUE;
2307: mat->assembled = PETSC_FALSE;
2308: }
2309: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2310: if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2311: else {
2312: PetscInt buf[8192], *bufr = NULL, *bufc = NULL;
2313: const PetscInt *irowm, *icolm;
2315: if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2316: bufr = buf;
2317: bufc = buf + nrow;
2318: irowm = bufr;
2319: icolm = bufc;
2320: } else {
2321: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2322: irowm = bufr;
2323: icolm = bufc;
2324: }
2325: if (mat->rmap->mapping) ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr);
2326: else irowm = irow;
2327: if (mat->cmap->mapping) {
2328: if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2329: ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc);
2330: } else icolm = irowm;
2331: } else icolm = icol;
2332: MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv);
2333: if (bufr != buf) PetscFree2(bufr, bufc);
2334: }
2335: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2336: return 0;
2337: }
2339: /*@C
2340: MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2341: using a local ordering of the nodes a block at a time.
2343: Not Collective
2345: Input Parameters:
2346: + x - the matrix
2347: . nrow, irow - number of rows and their local indices
2348: . ncol, icol - number of columns and their local indices
2349: . y - a logically two-dimensional array of values
2350: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2352: Notes:
2353: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2354: `MatSetUp()` before using this routine
2356: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2357: before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2359: Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2360: options cannot be mixed without intervening calls to the assembly
2361: routines.
2363: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2364: MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2366: Level: intermediate
2368: Developer Note:
2369: This is labeled with C so does not automatically generate Fortran stubs and interfaces
2370: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2372: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2373: `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2374: @*/
2375: PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2376: {
2380: MatCheckPreallocated(mat, 1);
2381: if (!nrow || !ncol) return 0; /* no values to insert */
2384: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2386: if (PetscDefined(USE_DEBUG)) {
2389: }
2391: if (mat->assembled) {
2392: mat->was_assembled = PETSC_TRUE;
2393: mat->assembled = PETSC_FALSE;
2394: }
2395: if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2396: PetscInt irbs, rbs;
2397: MatGetBlockSizes(mat, &rbs, NULL);
2398: ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs);
2400: }
2401: if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2402: PetscInt icbs, cbs;
2403: MatGetBlockSizes(mat, NULL, &cbs);
2404: ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs);
2406: }
2407: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2408: if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2409: else {
2410: PetscInt buf[8192], *bufr = NULL, *bufc = NULL;
2411: const PetscInt *irowm, *icolm;
2413: if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2414: bufr = buf;
2415: bufc = buf + nrow;
2416: irowm = bufr;
2417: icolm = bufc;
2418: } else {
2419: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2420: irowm = bufr;
2421: icolm = bufc;
2422: }
2423: if (mat->rmap->mapping) ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr);
2424: else irowm = irow;
2425: if (mat->cmap->mapping) {
2426: if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2427: ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc);
2428: } else icolm = irowm;
2429: } else icolm = icol;
2430: MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv);
2431: if (bufr != buf) PetscFree2(bufr, bufc);
2432: }
2433: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2434: return 0;
2435: }
2437: /*@
2438: MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2440: Collective on mat
2442: Input Parameters:
2443: + mat - the matrix
2444: - x - the vector to be multiplied
2446: Output Parameters:
2447: . y - the result
2449: Note:
2450: The vectors x and y cannot be the same. I.e., one cannot
2451: call `MatMultDiagonalBlock`(A,y,y).
2453: Level: developer
2455: .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2456: @*/
2457: PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2458: {
2467: MatCheckPreallocated(mat, 1);
2469: PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2470: PetscObjectStateIncrease((PetscObject)y);
2471: return 0;
2472: }
2474: /* --------------------------------------------------------*/
2475: /*@
2476: MatMult - Computes the matrix-vector product, y = Ax.
2478: Neighbor-wise Collective on mat
2480: Input Parameters:
2481: + mat - the matrix
2482: - x - the vector to be multiplied
2484: Output Parameters:
2485: . y - the result
2487: Note:
2488: The vectors x and y cannot be the same. I.e., one cannot
2489: call `MatMult`(A,y,y).
2491: Level: beginner
2493: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2494: @*/
2495: PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2496: {
2508: VecSetErrorIfLocked(y, 3);
2509: if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2510: MatCheckPreallocated(mat, 1);
2512: VecLockReadPush(x);
2513: PetscLogEventBegin(MAT_Mult, mat, x, y, 0);
2514: PetscUseTypeMethod(mat, mult, x, y);
2515: PetscLogEventEnd(MAT_Mult, mat, x, y, 0);
2516: if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2517: VecLockReadPop(x);
2518: return 0;
2519: }
2521: /*@
2522: MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2524: Neighbor-wise Collective on mat
2526: Input Parameters:
2527: + mat - the matrix
2528: - x - the vector to be multiplied
2530: Output Parameters:
2531: . y - the result
2533: Notes:
2534: The vectors x and y cannot be the same. I.e., one cannot
2535: call `MatMultTranspose`(A,y,y).
2537: For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2538: use `MatMultHermitianTranspose()`
2540: Level: beginner
2542: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2543: @*/
2544: PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2545: {
2546: PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2560: if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2561: MatCheckPreallocated(mat, 1);
2563: if (!mat->ops->multtranspose) {
2564: if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2566: } else op = mat->ops->multtranspose;
2567: PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0);
2568: VecLockReadPush(x);
2569: (*op)(mat, x, y);
2570: VecLockReadPop(x);
2571: PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0);
2572: PetscObjectStateIncrease((PetscObject)y);
2573: if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2574: return 0;
2575: }
2577: /*@
2578: MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2580: Neighbor-wise Collective on mat
2582: Input Parameters:
2583: + mat - the matrix
2584: - x - the vector to be multilplied
2586: Output Parameters:
2587: . y - the result
2589: Notes:
2590: The vectors x and y cannot be the same. I.e., one cannot
2591: call `MatMultHermitianTranspose`(A,y,y).
2593: Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2595: For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2597: Level: beginner
2599: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2600: @*/
2601: PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2602: {
2615: MatCheckPreallocated(mat, 1);
2617: PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0);
2618: #if defined(PETSC_USE_COMPLEX)
2619: if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2620: VecLockReadPush(x);
2621: if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2622: else PetscUseTypeMethod(mat, mult, x, y);
2623: VecLockReadPop(x);
2624: } else {
2625: Vec w;
2626: VecDuplicate(x, &w);
2627: VecCopy(x, w);
2628: VecConjugate(w);
2629: MatMultTranspose(mat, w, y);
2630: VecDestroy(&w);
2631: VecConjugate(y);
2632: }
2633: PetscObjectStateIncrease((PetscObject)y);
2634: #else
2635: MatMultTranspose(mat, x, y);
2636: #endif
2637: PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0);
2638: return 0;
2639: }
2641: /*@
2642: MatMultAdd - Computes v3 = v2 + A * v1.
2644: Neighbor-wise Collective on mat
2646: Input Parameters:
2647: + mat - the matrix
2648: - v1, v2 - the vectors
2650: Output Parameters:
2651: . v3 - the result
2653: Note:
2654: The vectors v1 and v3 cannot be the same. I.e., one cannot
2655: call `MatMultAdd`(A,v1,v2,v1).
2657: Level: beginner
2659: .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2660: @*/
2661: PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2662: {
2677: MatCheckPreallocated(mat, 1);
2679: PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3);
2680: VecLockReadPush(v1);
2681: PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2682: VecLockReadPop(v1);
2683: PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3);
2684: PetscObjectStateIncrease((PetscObject)v3);
2685: return 0;
2686: }
2688: /*@
2689: MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2691: Neighbor-wise Collective on mat
2693: Input Parameters:
2694: + mat - the matrix
2695: - v1, v2 - the vectors
2697: Output Parameters:
2698: . v3 - the result
2700: Note:
2701: The vectors v1 and v3 cannot be the same. I.e., one cannot
2702: call `MatMultTransposeAdd`(A,v1,v2,v1).
2704: Level: beginner
2706: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2707: @*/
2708: PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2709: {
2710: PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2725: MatCheckPreallocated(mat, 1);
2727: PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3);
2728: VecLockReadPush(v1);
2729: (*op)(mat, v1, v2, v3);
2730: VecLockReadPop(v1);
2731: PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3);
2732: PetscObjectStateIncrease((PetscObject)v3);
2733: return 0;
2734: }
2736: /*@
2737: MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2739: Neighbor-wise Collective on mat
2741: Input Parameters:
2742: + mat - the matrix
2743: - v1, v2 - the vectors
2745: Output Parameters:
2746: . v3 - the result
2748: Note:
2749: The vectors v1 and v3 cannot be the same. I.e., one cannot
2750: call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2752: Level: beginner
2754: .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2755: @*/
2756: PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2757: {
2770: MatCheckPreallocated(mat, 1);
2772: PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2773: VecLockReadPush(v1);
2774: if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2775: else {
2776: Vec w, z;
2777: VecDuplicate(v1, &w);
2778: VecCopy(v1, w);
2779: VecConjugate(w);
2780: VecDuplicate(v3, &z);
2781: MatMultTranspose(mat, w, z);
2782: VecDestroy(&w);
2783: VecConjugate(z);
2784: if (v2 != v3) {
2785: VecWAXPY(v3, 1.0, v2, z);
2786: } else {
2787: VecAXPY(v3, 1.0, z);
2788: }
2789: VecDestroy(&z);
2790: }
2791: VecLockReadPop(v1);
2792: PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2793: PetscObjectStateIncrease((PetscObject)v3);
2794: return 0;
2795: }
2797: /*@C
2798: MatGetFactorType - gets the type of factorization it is
2800: Not Collective
2802: Input Parameters:
2803: . mat - the matrix
2805: Output Parameters:
2806: . 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`
2808: Level: intermediate
2810: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2811: `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2812: @*/
2813: PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2814: {
2818: *t = mat->factortype;
2819: return 0;
2820: }
2822: /*@C
2823: MatSetFactorType - sets the type of factorization it is
2825: Logically Collective on mat
2827: Input Parameters:
2828: + mat - the matrix
2829: - 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`
2831: Level: intermediate
2833: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2834: `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2835: @*/
2836: PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2837: {
2840: mat->factortype = t;
2841: return 0;
2842: }
2844: /* ------------------------------------------------------------*/
2845: /*@C
2846: MatGetInfo - Returns information about matrix storage (number of
2847: nonzeros, memory, etc.).
2849: Collective on mat if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2851: Input Parameter:
2852: . mat - the matrix
2854: Output Parameters:
2855: + flag - flag indicating the type of parameters to be returned
2856: (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors,
2857: MAT_GLOBAL_SUM - sum over all processors)
2858: - info - matrix information context
2860: Notes:
2861: The `MatInfo` context contains a variety of matrix data, including
2862: number of nonzeros allocated and used, number of mallocs during
2863: matrix assembly, etc. Additional information for factored matrices
2864: is provided (such as the fill ratio, number of mallocs during
2865: factorization, etc.). Much of this info is printed to `PETSC_STDOUT`
2866: when using the runtime options
2867: $ -info -mat_view ::ascii_info
2869: Example for C/C++ Users:
2870: See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2871: data within the MatInfo context. For example,
2872: .vb
2873: MatInfo info;
2874: Mat A;
2875: double mal, nz_a, nz_u;
2877: MatGetInfo(A,MAT_LOCAL,&info);
2878: mal = info.mallocs;
2879: nz_a = info.nz_allocated;
2880: .ve
2882: Example for Fortran Users:
2883: Fortran users should declare info as a double precision
2884: array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2885: of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2886: a complete list of parameter names.
2887: .vb
2888: double precision info(MAT_INFO_SIZE)
2889: double precision mal, nz_a
2890: Mat A
2891: integer ierr
2893: call MatGetInfo(A,MAT_LOCAL,info,ierr)
2894: mal = info(MAT_INFO_MALLOCS)
2895: nz_a = info(MAT_INFO_NZ_ALLOCATED)
2896: .ve
2898: Level: intermediate
2900: Developer Note: fortran interface is not autogenerated as the f90
2901: interface definition cannot be generated correctly [due to MatInfo]
2903: .seealso: `MatInfo`, `MatStashGetInfo()`
2904: @*/
2905: PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2906: {
2910: MatCheckPreallocated(mat, 1);
2911: PetscUseTypeMethod(mat, getinfo, flag, info);
2912: return 0;
2913: }
2915: /*
2916: This is used by external packages where it is not easy to get the info from the actual
2917: matrix factorization.
2918: */
2919: PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2920: {
2921: PetscMemzero(info, sizeof(MatInfo));
2922: return 0;
2923: }
2925: /* ----------------------------------------------------------*/
2927: /*@C
2928: MatLUFactor - Performs in-place LU factorization of matrix.
2930: Collective on mat
2932: Input Parameters:
2933: + mat - the matrix
2934: . row - row permutation
2935: . col - column permutation
2936: - info - options for factorization, includes
2937: $ fill - expected fill as ratio of original fill.
2938: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2939: $ Run with the option -info to determine an optimal value to use
2941: Notes:
2942: Most users should employ the `KSP` interface for linear solvers
2943: instead of working directly with matrix algebra routines such as this.
2944: See, e.g., `KSPCreate()`.
2946: This changes the state of the matrix to a factored matrix; it cannot be used
2947: for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
2949: This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
2950: when not using `KSP`.
2952: Level: developer
2954: Developer Note:
2955: The Fortran interface is not autogenerated as the f90
2956: interface definition cannot be generated correctly [due to `MatFactorInfo`]
2958: .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2959: `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2960: @*/
2961: PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
2962: {
2963: MatFactorInfo tinfo;
2972: MatCheckPreallocated(mat, 1);
2973: if (!info) {
2974: MatFactorInfoInitialize(&tinfo);
2975: info = &tinfo;
2976: }
2978: PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0);
2979: PetscUseTypeMethod(mat, lufactor, row, col, info);
2980: PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0);
2981: PetscObjectStateIncrease((PetscObject)mat);
2982: return 0;
2983: }
2985: /*@C
2986: MatILUFactor - Performs in-place ILU factorization of matrix.
2988: Collective on mat
2990: Input Parameters:
2991: + mat - the matrix
2992: . row - row permutation
2993: . col - column permutation
2994: - info - structure containing
2995: $ levels - number of levels of fill.
2996: $ expected fill - as ratio of original fill.
2997: $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices
2998: missing diagonal entries)
3000: Notes:
3001: Most users should employ the `KSP` interface for linear solvers
3002: instead of working directly with matrix algebra routines such as this.
3003: See, e.g., `KSPCreate()`.
3005: Probably really in-place only when level of fill is zero, otherwise allocates
3006: new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3007: when not using `KSP`.
3009: Level: developer
3011: Developer Note:
3012: The Fortran interface is not autogenerated as the f90
3013: interface definition cannot be generated correctly [due to MatFactorInfo]
3015: .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3016: @*/
3017: PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3018: {
3027: MatCheckPreallocated(mat, 1);
3029: PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0);
3030: PetscUseTypeMethod(mat, ilufactor, row, col, info);
3031: PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0);
3032: PetscObjectStateIncrease((PetscObject)mat);
3033: return 0;
3034: }
3036: /*@C
3037: MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3038: Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3040: Collective on fact
3042: Input Parameters:
3043: + fact - the factor matrix obtained with `MatGetFactor()`
3044: . mat - the matrix
3045: . row, col - row and column permutations
3046: - info - options for factorization, includes
3047: .vb
3048: fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3049: dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3050: .ve
3052: Notes:
3053: See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3055: Most users should employ the simplified `KSP` interface for linear solvers
3056: instead of working directly with matrix algebra routines such as this.
3057: See, e.g., `KSPCreate()`.
3059: Level: developer
3061: Developer Note:
3062: The Fortran interface is not autogenerated as the f90
3063: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3065: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3066: @*/
3067: PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3068: {
3069: MatFactorInfo tinfo;
3079: if (!(fact)->ops->lufactorsymbolic) {
3080: MatSolverType stype;
3081: MatFactorGetSolverType(fact, &stype);
3082: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3083: }
3084: MatCheckPreallocated(mat, 2);
3085: if (!info) {
3086: MatFactorInfoInitialize(&tinfo);
3087: info = &tinfo;
3088: }
3090: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0);
3091: (fact->ops->lufactorsymbolic)(fact, mat, row, col, info);
3092: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0);
3093: PetscObjectStateIncrease((PetscObject)fact);
3094: return 0;
3095: }
3097: /*@C
3098: MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3099: Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3101: Collective on fact
3103: Input Parameters:
3104: + fact - the factor matrix obtained with `MatGetFactor()`
3105: . mat - the matrix
3106: - info - options for factorization
3108: Notes:
3109: See `MatLUFactor()` for in-place factorization. See
3110: `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3112: Most users should employ the `KSP` interface for linear solvers
3113: instead of working directly with matrix algebra routines such as this.
3114: See, e.g., `KSPCreate()`.
3116: Level: developer
3118: Developer Note:
3119: The Fortran interface is not autogenerated as the f90
3120: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3122: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3123: @*/
3124: PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3125: {
3126: MatFactorInfo tinfo;
3134: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3137: MatCheckPreallocated(mat, 2);
3138: if (!info) {
3139: MatFactorInfoInitialize(&tinfo);
3140: info = &tinfo;
3141: }
3143: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0);
3144: else PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0);
3145: (fact->ops->lufactornumeric)(fact, mat, info);
3146: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0);
3147: else PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0);
3148: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3149: PetscObjectStateIncrease((PetscObject)fact);
3150: return 0;
3151: }
3153: /*@C
3154: MatCholeskyFactor - Performs in-place Cholesky factorization of a
3155: symmetric matrix.
3157: Collective on mat
3159: Input Parameters:
3160: + mat - the matrix
3161: . perm - row and column permutations
3162: - f - expected fill as ratio of original fill
3164: Notes:
3165: See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`,
3166: `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3168: Most users should employ the `KSP` interface for linear solvers
3169: instead of working directly with matrix algebra routines such as this.
3170: See, e.g., `KSPCreate()`.
3172: Level: developer
3174: Developer Note:
3175: The Fortran interface is not autogenerated as the f90
3176: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3178: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3179: `MatGetOrdering()`
3180: @*/
3181: PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3182: {
3183: MatFactorInfo tinfo;
3192: MatCheckPreallocated(mat, 1);
3193: if (!info) {
3194: MatFactorInfoInitialize(&tinfo);
3195: info = &tinfo;
3196: }
3198: PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0);
3199: PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3200: PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0);
3201: PetscObjectStateIncrease((PetscObject)mat);
3202: return 0;
3203: }
3205: /*@C
3206: MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3207: of a symmetric matrix.
3209: Collective on fact
3211: Input Parameters:
3212: + fact - the factor matrix obtained with `MatGetFactor()`
3213: . mat - the matrix
3214: . perm - row and column permutations
3215: - info - options for factorization, includes
3216: $ fill - expected fill as ratio of original fill.
3217: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3218: $ Run with the option -info to determine an optimal value to use
3220: Notes:
3221: See `MatLUFactorSymbolic()` for the nonsymmetric case. See also
3222: `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3224: Most users should employ the `KSP` interface for linear solvers
3225: instead of working directly with matrix algebra routines such as this.
3226: See, e.g., `KSPCreate()`.
3228: Level: developer
3230: Developer Note:
3231: The Fortran interface is not autogenerated as the f90
3232: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3234: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3235: `MatGetOrdering()`
3236: @*/
3237: PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3238: {
3239: MatFactorInfo tinfo;
3249: if (!(fact)->ops->choleskyfactorsymbolic) {
3250: MatSolverType stype;
3251: MatFactorGetSolverType(fact, &stype);
3252: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3253: }
3254: MatCheckPreallocated(mat, 2);
3255: if (!info) {
3256: MatFactorInfoInitialize(&tinfo);
3257: info = &tinfo;
3258: }
3260: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3261: (fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info);
3262: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3263: PetscObjectStateIncrease((PetscObject)fact);
3264: return 0;
3265: }
3267: /*@C
3268: MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3269: of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3270: `MatCholeskyFactorSymbolic()`.
3272: Collective on fact
3274: Input Parameters:
3275: + fact - the factor matrix obtained with `MatGetFactor()`
3276: . mat - the initial matrix
3277: . info - options for factorization
3278: - fact - the symbolic factor of mat
3280: Note:
3281: Most users should employ the `KSP` interface for linear solvers
3282: instead of working directly with matrix algebra routines such as this.
3283: See, e.g., `KSPCreate()`.
3285: Level: developer
3287: Developer Note:
3288: The Fortran interface is not autogenerated as the f90
3289: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3291: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3292: @*/
3293: PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3294: {
3295: MatFactorInfo tinfo;
3304: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3305: MatCheckPreallocated(mat, 2);
3306: if (!info) {
3307: MatFactorInfoInitialize(&tinfo);
3308: info = &tinfo;
3309: }
3311: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3312: else PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0);
3313: (fact->ops->choleskyfactornumeric)(fact, mat, info);
3314: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3315: else PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0);
3316: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3317: PetscObjectStateIncrease((PetscObject)fact);
3318: return 0;
3319: }
3321: /*@
3322: MatQRFactor - Performs in-place QR factorization of matrix.
3324: Collective on mat
3326: Input Parameters:
3327: + mat - the matrix
3328: . col - column permutation
3329: - info - options for factorization, includes
3330: $ fill - expected fill as ratio of original fill.
3331: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3332: $ Run with the option -info to determine an optimal value to use
3334: Notes:
3335: Most users should employ the `KSP` interface for linear solvers
3336: instead of working directly with matrix algebra routines such as this.
3337: See, e.g., `KSPCreate()`.
3339: This changes the state of the matrix to a factored matrix; it cannot be used
3340: for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3342: Level: developer
3344: Developer Note:
3345: The Fortran interface is not autogenerated as the f90
3346: interface definition cannot be generated correctly [due to MatFactorInfo]
3348: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3349: `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3350: @*/
3351: PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3352: {
3359: MatCheckPreallocated(mat, 1);
3360: PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0);
3361: PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3362: PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0);
3363: PetscObjectStateIncrease((PetscObject)mat);
3364: return 0;
3365: }
3367: /*@
3368: MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3369: Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3371: Collective on fact
3373: Input Parameters:
3374: + fact - the factor matrix obtained with `MatGetFactor()`
3375: . mat - the matrix
3376: . col - column permutation
3377: - info - options for factorization, includes
3378: $ fill - expected fill as ratio of original fill.
3379: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3380: $ Run with the option -info to determine an optimal value to use
3382: Most users should employ the `KSP` interface for linear solvers
3383: instead of working directly with matrix algebra routines such as this.
3384: See, e.g., `KSPCreate()`.
3386: Level: developer
3388: Developer Note:
3389: The Fortran interface is not autogenerated as the f90
3390: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3392: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3393: @*/
3394: PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3395: {
3396: MatFactorInfo tinfo;
3405: MatCheckPreallocated(mat, 2);
3406: if (!info) {
3407: MatFactorInfoInitialize(&tinfo);
3408: info = &tinfo;
3409: }
3411: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0);
3412: PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3413: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0);
3414: PetscObjectStateIncrease((PetscObject)fact);
3415: return 0;
3416: }
3418: /*@
3419: MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3420: Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3422: Collective on fact
3424: Input Parameters:
3425: + fact - the factor matrix obtained with `MatGetFactor()`
3426: . mat - the matrix
3427: - info - options for factorization
3429: Notes:
3430: See `MatQRFactor()` for in-place factorization.
3432: Most users should employ the `KSP` interface for linear solvers
3433: instead of working directly with matrix algebra routines such as this.
3434: See, e.g., `KSPCreate()`.
3436: Level: developer
3438: Developer Note:
3439: The Fortran interface is not autogenerated as the f90
3440: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3442: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3443: @*/
3444: PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3445: {
3446: MatFactorInfo tinfo;
3454: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3456: MatCheckPreallocated(mat, 2);
3457: if (!info) {
3458: MatFactorInfoInitialize(&tinfo);
3459: info = &tinfo;
3460: }
3462: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0);
3463: else PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0);
3464: PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3465: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0);
3466: else PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0);
3467: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3468: PetscObjectStateIncrease((PetscObject)fact);
3469: return 0;
3470: }
3472: /* ----------------------------------------------------------------*/
3473: /*@
3474: MatSolve - Solves A x = b, given a factored matrix.
3476: Neighbor-wise Collective on mat
3478: Input Parameters:
3479: + mat - the factored matrix
3480: - b - the right-hand-side vector
3482: Output Parameter:
3483: . x - the result vector
3485: Notes:
3486: The vectors b and x cannot be the same. I.e., one cannot
3487: call `MatSolve`(A,x,x).
3489: Most users should employ the `KSP` interface for linear solvers
3490: instead of working directly with matrix algebra routines such as this.
3491: See, e.g., `KSPCreate()`.
3493: Level: developer
3495: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3496: @*/
3497: PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3498: {
3509: if (!mat->rmap->N && !mat->cmap->N) return 0;
3510: MatCheckPreallocated(mat, 1);
3512: PetscLogEventBegin(MAT_Solve, mat, b, x, 0);
3513: if (mat->factorerrortype) {
3514: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3515: VecSetInf(x);
3516: } else PetscUseTypeMethod(mat, solve, b, x);
3517: PetscLogEventEnd(MAT_Solve, mat, b, x, 0);
3518: PetscObjectStateIncrease((PetscObject)x);
3519: return 0;
3520: }
3522: static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3523: {
3524: Vec b, x;
3525: PetscInt N, i;
3526: PetscErrorCode (*f)(Mat, Vec, Vec);
3527: PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3529: if (A->factorerrortype) {
3530: PetscInfo(A, "MatFactorError %d\n", A->factorerrortype);
3531: MatSetInf(X);
3532: return 0;
3533: }
3534: f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3536: MatBoundToCPU(A, &Abound);
3537: if (!Abound) {
3538: PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "");
3539: PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "");
3540: }
3541: #if defined(PETSC_HAVE_CUDA)
3542: if (Bneedconv) MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B);
3543: if (Xneedconv) MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X);
3544: #elif (PETSC_HAVE_HIP)
3545: if (Bneedconv) MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B);
3546: if (Xneedconv) MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X);
3547: #endif
3548: MatGetSize(B, NULL, &N);
3549: for (i = 0; i < N; i++) {
3550: MatDenseGetColumnVecRead(B, i, &b);
3551: MatDenseGetColumnVecWrite(X, i, &x);
3552: (*f)(A, b, x);
3553: MatDenseRestoreColumnVecWrite(X, i, &x);
3554: MatDenseRestoreColumnVecRead(B, i, &b);
3555: }
3556: if (Bneedconv) MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B);
3557: if (Xneedconv) MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X);
3558: return 0;
3559: }
3561: /*@
3562: MatMatSolve - Solves A X = B, given a factored matrix.
3564: Neighbor-wise Collective on A
3566: Input Parameters:
3567: + A - the factored matrix
3568: - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3570: Output Parameter:
3571: . X - the result matrix (dense matrix)
3573: Note:
3574: If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO;
3575: otherwise, B and X cannot be the same.
3577: Level: developer
3579: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3580: @*/
3581: PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3582: {
3592: if (!A->rmap->N && !A->cmap->N) return 0;
3594: MatCheckPreallocated(A, 1);
3596: PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3597: if (!A->ops->matsolve) {
3598: PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name);
3599: MatMatSolve_Basic(A, B, X, PETSC_FALSE);
3600: } else PetscUseTypeMethod(A, matsolve, B, X);
3601: PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3602: PetscObjectStateIncrease((PetscObject)X);
3603: return 0;
3604: }
3606: /*@
3607: MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3609: Neighbor-wise Collective on A
3611: Input Parameters:
3612: + A - the factored matrix
3613: - B - the right-hand-side matrix (`MATDENSE` matrix)
3615: Output Parameter:
3616: . X - the result matrix (dense matrix)
3618: Note:
3619: The matrices B and X cannot be the same. I.e., one cannot
3620: call `MatMatSolveTranspose`(A,X,X).
3622: Level: developer
3624: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3625: @*/
3626: PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3627: {
3639: if (!A->rmap->N && !A->cmap->N) return 0;
3641: MatCheckPreallocated(A, 1);
3643: PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3644: if (!A->ops->matsolvetranspose) {
3645: PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name);
3646: MatMatSolve_Basic(A, B, X, PETSC_TRUE);
3647: } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3648: PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3649: PetscObjectStateIncrease((PetscObject)X);
3650: return 0;
3651: }
3653: /*@
3654: MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3656: Neighbor-wise Collective on A
3658: Input Parameters:
3659: + A - the factored matrix
3660: - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3662: Output Parameter:
3663: . X - the result matrix (dense matrix)
3665: Note:
3666: For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row
3667: format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3669: Level: developer
3671: .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3672: @*/
3673: PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3674: {
3686: if (!A->rmap->N && !A->cmap->N) return 0;
3688: MatCheckPreallocated(A, 1);
3690: PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0);
3691: PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3692: PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0);
3693: PetscObjectStateIncrease((PetscObject)X);
3694: return 0;
3695: }
3697: /*@
3698: MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3699: U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3701: Neighbor-wise Collective on mat
3703: Input Parameters:
3704: + mat - the factored matrix
3705: - b - the right-hand-side vector
3707: Output Parameter:
3708: . x - the result vector
3710: Notes:
3711: `MatSolve()` should be used for most applications, as it performs
3712: a forward solve followed by a backward solve.
3714: The vectors b and x cannot be the same, i.e., one cannot
3715: call `MatForwardSolve`(A,x,x).
3717: For matrix in `MATSEQBAIJ` format with block size larger than 1,
3718: the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3719: `MatForwardSolve()` solves U^T*D y = b, and
3720: `MatBackwardSolve()` solves U x = y.
3721: Thus they do not provide a symmetric preconditioner.
3723: Level: developer
3725: .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3726: @*/
3727: PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3728: {
3739: if (!mat->rmap->N && !mat->cmap->N) return 0;
3740: MatCheckPreallocated(mat, 1);
3742: PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0);
3743: PetscUseTypeMethod(mat, forwardsolve, b, x);
3744: PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0);
3745: PetscObjectStateIncrease((PetscObject)x);
3746: return 0;
3747: }
3749: /*@
3750: MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3751: D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3753: Neighbor-wise Collective on mat
3755: Input Parameters:
3756: + mat - the factored matrix
3757: - b - the right-hand-side vector
3759: Output Parameter:
3760: . x - the result vector
3762: Notes:
3763: `MatSolve()` should be used for most applications, as it performs
3764: a forward solve followed by a backward solve.
3766: The vectors b and x cannot be the same. I.e., one cannot
3767: call `MatBackwardSolve`(A,x,x).
3769: For matrix in `MATSEQBAIJ` format with block size larger than 1,
3770: the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3771: `MatForwardSolve()` solves U^T*D y = b, and
3772: `MatBackwardSolve()` solves U x = y.
3773: Thus they do not provide a symmetric preconditioner.
3775: Level: developer
3777: .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3778: @*/
3779: PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3780: {
3791: if (!mat->rmap->N && !mat->cmap->N) return 0;
3792: MatCheckPreallocated(mat, 1);
3794: PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0);
3795: PetscUseTypeMethod(mat, backwardsolve, b, x);
3796: PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0);
3797: PetscObjectStateIncrease((PetscObject)x);
3798: return 0;
3799: }
3801: /*@
3802: MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3804: Neighbor-wise Collective on mat
3806: Input Parameters:
3807: + mat - the factored matrix
3808: . b - the right-hand-side vector
3809: - y - the vector to be added to
3811: Output Parameter:
3812: . x - the result vector
3814: Note:
3815: The vectors b and x cannot be the same. I.e., one cannot
3816: call `MatSolveAdd`(A,x,y,x).
3818: Level: developer
3820: .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3821: @*/
3822: PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3823: {
3824: PetscScalar one = 1.0;
3825: Vec tmp;
3841: if (!mat->rmap->N && !mat->cmap->N) return 0;
3842: MatCheckPreallocated(mat, 1);
3844: PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y);
3845: if (mat->factorerrortype) {
3846: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3847: VecSetInf(x);
3848: } else if (mat->ops->solveadd) {
3849: PetscUseTypeMethod(mat, solveadd, b, y, x);
3850: } else {
3851: /* do the solve then the add manually */
3852: if (x != y) {
3853: MatSolve(mat, b, x);
3854: VecAXPY(x, one, y);
3855: } else {
3856: VecDuplicate(x, &tmp);
3857: VecCopy(x, tmp);
3858: MatSolve(mat, b, x);
3859: VecAXPY(x, one, tmp);
3860: VecDestroy(&tmp);
3861: }
3862: }
3863: PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y);
3864: PetscObjectStateIncrease((PetscObject)x);
3865: return 0;
3866: }
3868: /*@
3869: MatSolveTranspose - Solves A' x = b, given a factored matrix.
3871: Neighbor-wise Collective on mat
3873: Input Parameters:
3874: + mat - the factored matrix
3875: - b - the right-hand-side vector
3877: Output Parameter:
3878: . x - the result vector
3880: Notes:
3881: The vectors b and x cannot be the same. I.e., one cannot
3882: call `MatSolveTranspose`(A,x,x).
3884: Most users should employ the `KSP` interface for linear solvers
3885: instead of working directly with matrix algebra routines such as this.
3886: See, e.g., `KSPCreate()`.
3888: Level: developer
3890: .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3891: @*/
3892: PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3893: {
3894: PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3905: if (!mat->rmap->N && !mat->cmap->N) return 0;
3906: MatCheckPreallocated(mat, 1);
3907: PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0);
3908: if (mat->factorerrortype) {
3909: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3910: VecSetInf(x);
3911: } else {
3913: (*f)(mat, b, x);
3914: }
3915: PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0);
3916: PetscObjectStateIncrease((PetscObject)x);
3917: return 0;
3918: }
3920: /*@
3921: MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3922: factored matrix.
3924: Neighbor-wise Collective on mat
3926: Input Parameters:
3927: + mat - the factored matrix
3928: . b - the right-hand-side vector
3929: - y - the vector to be added to
3931: Output Parameter:
3932: . x - the result vector
3934: Note:
3935: The vectors b and x cannot be the same. I.e., one cannot
3936: call `MatSolveTransposeAdd`(A,x,y,x).
3938: Level: developer
3940: .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
3941: @*/
3942: PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
3943: {
3944: PetscScalar one = 1.0;
3945: Vec tmp;
3946: PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
3961: if (!mat->rmap->N && !mat->cmap->N) return 0;
3962: MatCheckPreallocated(mat, 1);
3964: PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y);
3965: if (mat->factorerrortype) {
3966: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3967: VecSetInf(x);
3968: } else if (f) {
3969: (*f)(mat, b, y, x);
3970: } else {
3971: /* do the solve then the add manually */
3972: if (x != y) {
3973: MatSolveTranspose(mat, b, x);
3974: VecAXPY(x, one, y);
3975: } else {
3976: VecDuplicate(x, &tmp);
3977: VecCopy(x, tmp);
3978: MatSolveTranspose(mat, b, x);
3979: VecAXPY(x, one, tmp);
3980: VecDestroy(&tmp);
3981: }
3982: }
3983: PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y);
3984: PetscObjectStateIncrease((PetscObject)x);
3985: return 0;
3986: }
3987: /* ----------------------------------------------------------------*/
3989: /*@
3990: MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
3992: Neighbor-wise Collective on mat
3994: Input Parameters:
3995: + mat - the matrix
3996: . b - the right hand side
3997: . omega - the relaxation factor
3998: . flag - flag indicating the type of SOR (see below)
3999: . shift - diagonal shift
4000: . its - the number of iterations
4001: - lits - the number of local iterations
4003: Output Parameter:
4004: . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4006: SOR Flags:
4007: + `SOR_FORWARD_SWEEP` - forward SOR
4008: . `SOR_BACKWARD_SWEEP` - backward SOR
4009: . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4010: . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4011: . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4012: . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4013: . `SOR_EISENSTAT` - SOR with Eisenstat trick
4014: . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4015: upper/lower triangular part of matrix to
4016: vector (with omega)
4017: - `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4019: Notes:
4020: `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4021: `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4022: on each processor.
4024: Application programmers will not generally use `MatSOR()` directly,
4025: but instead will employ the `KSP`/`PC` interface.
4027: For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4029: Most users should employ the `KSP` interface for linear solvers
4030: instead of working directly with matrix algebra routines such as this.
4031: See, e.g., `KSPCreate()`.
4033: Vectors x and b CANNOT be the same
4035: Notes for Advanced Users:
4036: The flags are implemented as bitwise inclusive or operations.
4037: For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4038: to specify a zero initial guess for SSOR.
4040: Developer Note:
4041: We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4043: Level: developer
4045: .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4046: @*/
4047: PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4048: {
4064: MatCheckPreallocated(mat, 1);
4065: PetscLogEventBegin(MAT_SOR, mat, b, x, 0);
4066: PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4067: PetscLogEventEnd(MAT_SOR, mat, b, x, 0);
4068: PetscObjectStateIncrease((PetscObject)x);
4069: return 0;
4070: }
4072: /*
4073: Default matrix copy routine.
4074: */
4075: PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4076: {
4077: PetscInt i, rstart = 0, rend = 0, nz;
4078: const PetscInt *cwork;
4079: const PetscScalar *vwork;
4081: if (B->assembled) MatZeroEntries(B);
4082: if (str == SAME_NONZERO_PATTERN) {
4083: MatGetOwnershipRange(A, &rstart, &rend);
4084: for (i = rstart; i < rend; i++) {
4085: MatGetRow(A, i, &nz, &cwork, &vwork);
4086: MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES);
4087: MatRestoreRow(A, i, &nz, &cwork, &vwork);
4088: }
4089: } else {
4090: MatAYPX(B, 0.0, A, str);
4091: }
4092: MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);
4093: MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);
4094: return 0;
4095: }
4097: /*@
4098: MatCopy - Copies a matrix to another matrix.
4100: Collective on A
4102: Input Parameters:
4103: + A - the matrix
4104: - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4106: Output Parameter:
4107: . B - where the copy is put
4109: Notes:
4110: If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4112: `MatCopy()` copies the matrix entries of a matrix to another existing
4113: matrix (after first zeroing the second matrix). A related routine is
4114: `MatConvert()`, which first creates a new matrix and then copies the data.
4116: Level: intermediate
4118: .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4119: @*/
4120: PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4121: {
4122: PetscInt i;
4129: MatCheckPreallocated(B, 2);
4133: A->cmap->N, B->cmap->N);
4134: MatCheckPreallocated(A, 1);
4135: if (A == B) return 0;
4137: PetscLogEventBegin(MAT_Copy, A, B, 0, 0);
4138: if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4139: else MatCopy_Basic(A, B, str);
4141: B->stencil.dim = A->stencil.dim;
4142: B->stencil.noc = A->stencil.noc;
4143: for (i = 0; i <= A->stencil.dim; i++) {
4144: B->stencil.dims[i] = A->stencil.dims[i];
4145: B->stencil.starts[i] = A->stencil.starts[i];
4146: }
4148: PetscLogEventEnd(MAT_Copy, A, B, 0, 0);
4149: PetscObjectStateIncrease((PetscObject)B);
4150: return 0;
4151: }
4153: /*@C
4154: MatConvert - Converts a matrix to another matrix, either of the same
4155: or different type.
4157: Collective on mat
4159: Input Parameters:
4160: + mat - the matrix
4161: . newtype - new matrix type. Use `MATSAME` to create a new matrix of the
4162: same type as the original matrix.
4163: - reuse - denotes if the destination matrix is to be created or reused.
4164: 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
4165: `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).
4167: Output Parameter:
4168: . M - pointer to place new matrix
4170: Notes:
4171: `MatConvert()` first creates a new matrix and then copies the data from
4172: the first matrix. A related routine is `MatCopy()`, which copies the matrix
4173: entries of one matrix to another already existing matrix context.
4175: Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4176: the MPI communicator of the generated matrix is always the same as the communicator
4177: of the input matrix.
4179: Level: intermediate
4181: .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4182: @*/
4183: PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4184: {
4185: PetscBool sametype, issame, flg;
4186: PetscBool3 issymmetric, ishermitian;
4187: char convname[256], mtype[256];
4188: Mat B;
4195: MatCheckPreallocated(mat, 1);
4197: PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg);
4198: if (flg) newtype = mtype;
4200: PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype);
4201: PetscStrcmp(newtype, "same", &issame);
4205: if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4206: PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4207: return 0;
4208: }
4210: /* Cache Mat options because some converters use MatHeaderReplace */
4211: issymmetric = mat->symmetric;
4212: ishermitian = mat->hermitian;
4214: if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4215: PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4216: PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4217: } else {
4218: PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4219: const char *prefix[3] = {"seq", "mpi", ""};
4220: PetscInt i;
4221: /*
4222: Order of precedence:
4223: 0) See if newtype is a superclass of the current matrix.
4224: 1) See if a specialized converter is known to the current matrix.
4225: 2) See if a specialized converter is known to the desired matrix class.
4226: 3) See if a good general converter is registered for the desired class
4227: (as of 6/27/03 only MATMPIADJ falls into this category).
4228: 4) See if a good general converter is known for the current matrix.
4229: 5) Use a really basic converter.
4230: */
4232: /* 0) See if newtype is a superclass of the current matrix.
4233: i.e mat is mpiaij and newtype is aij */
4234: for (i = 0; i < 2; i++) {
4235: PetscStrncpy(convname, prefix[i], sizeof(convname));
4236: PetscStrlcat(convname, newtype, sizeof(convname));
4237: PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg);
4238: PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg);
4239: if (flg) {
4240: if (reuse == MAT_INPLACE_MATRIX) {
4241: PetscInfo(mat, "Early return\n");
4242: return 0;
4243: } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4244: PetscInfo(mat, "Calling MatDuplicate\n");
4245: PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4246: return 0;
4247: } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4248: PetscInfo(mat, "Calling MatCopy\n");
4249: MatCopy(mat, *M, SAME_NONZERO_PATTERN);
4250: return 0;
4251: }
4252: }
4253: }
4254: /* 1) See if a specialized converter is known to the current matrix and the desired class */
4255: for (i = 0; i < 3; i++) {
4256: PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4257: PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4258: PetscStrlcat(convname, "_", sizeof(convname));
4259: PetscStrlcat(convname, prefix[i], sizeof(convname));
4260: PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname));
4261: PetscStrlcat(convname, "_C", sizeof(convname));
4262: PetscObjectQueryFunction((PetscObject)mat, convname, &conv);
4263: PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv);
4264: if (conv) goto foundconv;
4265: }
4267: /* 2) See if a specialized converter is known to the desired matrix class. */
4268: MatCreate(PetscObjectComm((PetscObject)mat), &B);
4269: MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
4270: MatSetType(B, newtype);
4271: for (i = 0; i < 3; i++) {
4272: PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4273: PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4274: PetscStrlcat(convname, "_", sizeof(convname));
4275: PetscStrlcat(convname, prefix[i], sizeof(convname));
4276: PetscStrlcat(convname, newtype, sizeof(convname));
4277: PetscStrlcat(convname, "_C", sizeof(convname));
4278: PetscObjectQueryFunction((PetscObject)B, convname, &conv);
4279: PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv);
4280: if (conv) {
4281: MatDestroy(&B);
4282: goto foundconv;
4283: }
4284: }
4286: /* 3) See if a good general converter is registered for the desired class */
4287: conv = B->ops->convertfrom;
4288: PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv);
4289: MatDestroy(&B);
4290: if (conv) goto foundconv;
4292: /* 4) See if a good general converter is known for the current matrix */
4293: if (mat->ops->convert) conv = mat->ops->convert;
4294: PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv);
4295: if (conv) goto foundconv;
4297: /* 5) Use a really basic converter. */
4298: PetscInfo(mat, "Using MatConvert_Basic\n");
4299: conv = MatConvert_Basic;
4301: foundconv:
4302: PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4303: (*conv)(mat, newtype, reuse, M);
4304: if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4305: /* the block sizes must be same if the mappings are copied over */
4306: (*M)->rmap->bs = mat->rmap->bs;
4307: (*M)->cmap->bs = mat->cmap->bs;
4308: PetscObjectReference((PetscObject)mat->rmap->mapping);
4309: PetscObjectReference((PetscObject)mat->cmap->mapping);
4310: (*M)->rmap->mapping = mat->rmap->mapping;
4311: (*M)->cmap->mapping = mat->cmap->mapping;
4312: }
4313: (*M)->stencil.dim = mat->stencil.dim;
4314: (*M)->stencil.noc = mat->stencil.noc;
4315: for (i = 0; i <= mat->stencil.dim; i++) {
4316: (*M)->stencil.dims[i] = mat->stencil.dims[i];
4317: (*M)->stencil.starts[i] = mat->stencil.starts[i];
4318: }
4319: PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4320: }
4321: PetscObjectStateIncrease((PetscObject)*M);
4323: /* Copy Mat options */
4324: if (issymmetric == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE);
4325: else if (issymmetric == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE);
4326: if (ishermitian == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE);
4327: else if (ishermitian == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE);
4328: return 0;
4329: }
4331: /*@C
4332: MatFactorGetSolverType - Returns name of the package providing the factorization routines
4334: Not Collective
4336: Input Parameter:
4337: . mat - the matrix, must be a factored matrix
4339: Output Parameter:
4340: . type - the string name of the package (do not free this string)
4342: Note:
4343: In Fortran you pass in a empty string and the package name will be copied into it.
4344: (Make sure the string is long enough)
4346: Level: intermediate
4348: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4349: @*/
4350: PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4351: {
4352: PetscErrorCode (*conv)(Mat, MatSolverType *);
4358: PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv);
4359: if (conv) (*conv)(mat, type);
4360: else *type = MATSOLVERPETSC;
4361: return 0;
4362: }
4364: typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4365: struct _MatSolverTypeForSpecifcType {
4366: MatType mtype;
4367: /* no entry for MAT_FACTOR_NONE */
4368: PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4369: MatSolverTypeForSpecifcType next;
4370: };
4372: typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4373: struct _MatSolverTypeHolder {
4374: char *name;
4375: MatSolverTypeForSpecifcType handlers;
4376: MatSolverTypeHolder next;
4377: };
4379: static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4381: /*@C
4382: MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4384: Input Parameters:
4385: + package - name of the package, for example petsc or superlu
4386: . mtype - the matrix type that works with this package
4387: . ftype - the type of factorization supported by the package
4388: - createfactor - routine that will create the factored matrix ready to be used
4390: Level: developer
4392: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4393: @*/
4394: PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4395: {
4396: MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL;
4397: PetscBool flg;
4398: MatSolverTypeForSpecifcType inext, iprev = NULL;
4400: MatInitializePackage();
4401: if (!next) {
4402: PetscNew(&MatSolverTypeHolders);
4403: PetscStrallocpy(package, &MatSolverTypeHolders->name);
4404: PetscNew(&MatSolverTypeHolders->handlers);
4405: PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype);
4406: MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4407: return 0;
4408: }
4409: while (next) {
4410: PetscStrcasecmp(package, next->name, &flg);
4411: if (flg) {
4413: inext = next->handlers;
4414: while (inext) {
4415: PetscStrcasecmp(mtype, inext->mtype, &flg);
4416: if (flg) {
4417: inext->createfactor[(int)ftype - 1] = createfactor;
4418: return 0;
4419: }
4420: iprev = inext;
4421: inext = inext->next;
4422: }
4423: PetscNew(&iprev->next);
4424: PetscStrallocpy(mtype, (char **)&iprev->next->mtype);
4425: iprev->next->createfactor[(int)ftype - 1] = createfactor;
4426: return 0;
4427: }
4428: prev = next;
4429: next = next->next;
4430: }
4431: PetscNew(&prev->next);
4432: PetscStrallocpy(package, &prev->next->name);
4433: PetscNew(&prev->next->handlers);
4434: PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype);
4435: prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4436: return 0;
4437: }
4439: /*@C
4440: MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4442: Input Parameters:
4443: + type - name of the package, for example petsc or superlu
4444: . ftype - the type of factorization supported by the type
4445: - mtype - the matrix type that works with this type
4447: Output Parameters:
4448: + foundtype - `PETSC_TRUE` if the type was registered
4449: . foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4450: - createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4452: Level: developer
4454: .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4455: @*/
4456: PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4457: {
4458: MatSolverTypeHolder next = MatSolverTypeHolders;
4459: PetscBool flg;
4460: MatSolverTypeForSpecifcType inext;
4462: if (foundtype) *foundtype = PETSC_FALSE;
4463: if (foundmtype) *foundmtype = PETSC_FALSE;
4464: if (createfactor) *createfactor = NULL;
4466: if (type) {
4467: while (next) {
4468: PetscStrcasecmp(type, next->name, &flg);
4469: if (flg) {
4470: if (foundtype) *foundtype = PETSC_TRUE;
4471: inext = next->handlers;
4472: while (inext) {
4473: PetscStrbeginswith(mtype, inext->mtype, &flg);
4474: if (flg) {
4475: if (foundmtype) *foundmtype = PETSC_TRUE;
4476: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4477: return 0;
4478: }
4479: inext = inext->next;
4480: }
4481: }
4482: next = next->next;
4483: }
4484: } else {
4485: while (next) {
4486: inext = next->handlers;
4487: while (inext) {
4488: PetscStrcmp(mtype, inext->mtype, &flg);
4489: if (flg && inext->createfactor[(int)ftype - 1]) {
4490: if (foundtype) *foundtype = PETSC_TRUE;
4491: if (foundmtype) *foundmtype = PETSC_TRUE;
4492: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4493: return 0;
4494: }
4495: inext = inext->next;
4496: }
4497: next = next->next;
4498: }
4499: /* try with base classes inext->mtype */
4500: next = MatSolverTypeHolders;
4501: while (next) {
4502: inext = next->handlers;
4503: while (inext) {
4504: PetscStrbeginswith(mtype, inext->mtype, &flg);
4505: if (flg && inext->createfactor[(int)ftype - 1]) {
4506: if (foundtype) *foundtype = PETSC_TRUE;
4507: if (foundmtype) *foundmtype = PETSC_TRUE;
4508: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4509: return 0;
4510: }
4511: inext = inext->next;
4512: }
4513: next = next->next;
4514: }
4515: }
4516: return 0;
4517: }
4519: PetscErrorCode MatSolverTypeDestroy(void)
4520: {
4521: MatSolverTypeHolder next = MatSolverTypeHolders, prev;
4522: MatSolverTypeForSpecifcType inext, iprev;
4524: while (next) {
4525: PetscFree(next->name);
4526: inext = next->handlers;
4527: while (inext) {
4528: PetscFree(inext->mtype);
4529: iprev = inext;
4530: inext = inext->next;
4531: PetscFree(iprev);
4532: }
4533: prev = next;
4534: next = next->next;
4535: PetscFree(prev);
4536: }
4537: MatSolverTypeHolders = NULL;
4538: return 0;
4539: }
4541: /*@C
4542: MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4544: Logically Collective on mat
4546: Input Parameters:
4547: . mat - the matrix
4549: Output Parameters:
4550: . flg - `PETSC_TRUE` if uses the ordering
4552: Note:
4553: Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4554: packages do not, thus we want to skip generating the ordering when it is not needed or used.
4556: Level: developer
4558: .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4559: @*/
4560: PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4561: {
4562: *flg = mat->canuseordering;
4563: return 0;
4564: }
4566: /*@C
4567: MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4569: Logically Collective on mat
4571: Input Parameters:
4572: . mat - the matrix obtained with `MatGetFactor()`
4574: Output Parameters:
4575: . otype - the preferred type
4577: Level: developer
4579: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4580: @*/
4581: PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4582: {
4583: *otype = mat->preferredordering[ftype];
4585: return 0;
4586: }
4588: /*@C
4589: MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4591: Collective on mat
4593: Input Parameters:
4594: + mat - the matrix
4595: . type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4596: - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4598: Output Parameters:
4599: . f - the factor matrix used with MatXXFactorSymbolic() calls
4601: Options Database Key:
4602: . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4603: One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4605: Notes:
4606: Users usually access the factorization solvers via `KSP`
4608: Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4609: such as pastix, superlu, mumps etc.
4611: PETSc must have been ./configure to use the external solver, using the option --download-package
4613: Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4614: where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4615: call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix.
4617: Developer Note:
4618: This should actually be called `MatCreateFactor()` since it creates a new factor object
4620: Level: intermediate
4622: .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4623: `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4624: @*/
4625: PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4626: {
4627: PetscBool foundtype, foundmtype;
4628: PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4634: MatCheckPreallocated(mat, 1);
4636: MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv);
4637: if (!foundtype) {
4638: if (type) {
4639: 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],
4640: ((PetscObject)mat)->type_name, type);
4641: } else {
4642: 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);
4643: }
4644: }
4648: (*conv)(mat, ftype, f);
4649: if (mat->factorprefix) MatSetOptionsPrefix(*f, mat->factorprefix);
4650: return 0;
4651: }
4653: /*@C
4654: MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4656: Not Collective
4658: Input Parameters:
4659: + mat - the matrix
4660: . type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4661: - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4663: Output Parameter:
4664: . flg - PETSC_TRUE if the factorization is available
4666: Notes:
4667: Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4668: such as pastix, superlu, mumps etc.
4670: PETSc must have been ./configure to use the external solver, using the option --download-package
4672: Developer Note:
4673: This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4675: Level: intermediate
4677: .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4678: `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4679: @*/
4680: PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4681: {
4682: PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4689: MatCheckPreallocated(mat, 1);
4691: MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv);
4692: *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4693: return 0;
4694: }
4696: /*@
4697: MatDuplicate - Duplicates a matrix including the non-zero structure.
4699: Collective on mat
4701: Input Parameters:
4702: + mat - the matrix
4703: - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4704: See the manual page for `MatDuplicateOption()` for an explanation of these options.
4706: Output Parameter:
4707: . M - pointer to place new matrix
4709: Level: intermediate
4711: Notes:
4712: You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4714: 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.
4716: When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the simple matrix data structure of mat
4717: is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4718: User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4720: .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4721: @*/
4722: PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4723: {
4724: Mat B;
4725: VecType vtype;
4726: PetscInt i;
4727: PetscObject dm;
4728: void (*viewf)(void);
4735: MatCheckPreallocated(mat, 1);
4737: *M = NULL;
4738: PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4739: PetscUseTypeMethod(mat, duplicate, op, M);
4740: PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4741: B = *M;
4743: MatGetOperation(mat, MATOP_VIEW, &viewf);
4744: if (viewf) MatSetOperation(B, MATOP_VIEW, viewf);
4745: MatGetVecType(mat, &vtype);
4746: MatSetVecType(B, vtype);
4748: B->stencil.dim = mat->stencil.dim;
4749: B->stencil.noc = mat->stencil.noc;
4750: for (i = 0; i <= mat->stencil.dim; i++) {
4751: B->stencil.dims[i] = mat->stencil.dims[i];
4752: B->stencil.starts[i] = mat->stencil.starts[i];
4753: }
4755: B->nooffproczerorows = mat->nooffproczerorows;
4756: B->nooffprocentries = mat->nooffprocentries;
4758: PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm);
4759: if (dm) PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm);
4760: PetscObjectStateIncrease((PetscObject)B);
4761: return 0;
4762: }
4764: /*@
4765: MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4767: Logically Collective on mat
4769: Input Parameters:
4770: + mat - the matrix
4771: - v - the vector for storing the diagonal
4773: Output Parameter:
4774: . v - the diagonal of the matrix
4776: Level: intermediate
4778: Note:
4779: Currently only correct in parallel for square matrices.
4781: .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4782: @*/
4783: PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4784: {
4789: MatCheckPreallocated(mat, 1);
4791: PetscUseTypeMethod(mat, getdiagonal, v);
4792: PetscObjectStateIncrease((PetscObject)v);
4793: return 0;
4794: }
4796: /*@C
4797: MatGetRowMin - Gets the minimum value (of the real part) of each
4798: row of the matrix
4800: Logically Collective on mat
4802: Input Parameter:
4803: . mat - the matrix
4805: Output Parameters:
4806: + v - the vector for storing the maximums
4807: - idx - the indices of the column found for each row (optional)
4809: Level: intermediate
4811: Note:
4812: The result of this call are the same as if one converted the matrix to dense format
4813: and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4815: This code is only implemented for a couple of matrix formats.
4817: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4818: `MatGetRowMax()`
4819: @*/
4820: PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4821: {
4827: if (!mat->cmap->N) {
4828: VecSet(v, PETSC_MAX_REAL);
4829: if (idx) {
4830: PetscInt i, m = mat->rmap->n;
4831: for (i = 0; i < m; i++) idx[i] = -1;
4832: }
4833: } else {
4834: MatCheckPreallocated(mat, 1);
4835: }
4836: PetscUseTypeMethod(mat, getrowmin, v, idx);
4837: PetscObjectStateIncrease((PetscObject)v);
4838: return 0;
4839: }
4841: /*@C
4842: MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4843: row of the matrix
4845: Logically Collective on mat
4847: Input Parameter:
4848: . mat - the matrix
4850: Output Parameters:
4851: + v - the vector for storing the minimums
4852: - idx - the indices of the column found for each row (or NULL if not needed)
4854: Level: intermediate
4856: Notes:
4857: if a row is completely empty or has only 0.0 values then the idx[] value for that
4858: row is 0 (the first column).
4860: This code is only implemented for a couple of matrix formats.
4862: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4863: @*/
4864: PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4865: {
4872: if (!mat->cmap->N) {
4873: VecSet(v, 0.0);
4874: if (idx) {
4875: PetscInt i, m = mat->rmap->n;
4876: for (i = 0; i < m; i++) idx[i] = -1;
4877: }
4878: } else {
4879: MatCheckPreallocated(mat, 1);
4880: if (idx) PetscArrayzero(idx, mat->rmap->n);
4881: PetscUseTypeMethod(mat, getrowminabs, v, idx);
4882: }
4883: PetscObjectStateIncrease((PetscObject)v);
4884: return 0;
4885: }
4887: /*@C
4888: MatGetRowMax - Gets the maximum value (of the real part) of each
4889: row of the matrix
4891: Logically Collective on mat
4893: Input Parameter:
4894: . mat - the matrix
4896: Output Parameters:
4897: + v - the vector for storing the maximums
4898: - idx - the indices of the column found for each row (optional)
4900: Level: intermediate
4902: Notes:
4903: The result of this call are the same as if one converted the matrix to dense format
4904: and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4906: This code is only implemented for a couple of matrix formats.
4908: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4909: @*/
4910: PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
4911: {
4917: if (!mat->cmap->N) {
4918: VecSet(v, PETSC_MIN_REAL);
4919: if (idx) {
4920: PetscInt i, m = mat->rmap->n;
4921: for (i = 0; i < m; i++) idx[i] = -1;
4922: }
4923: } else {
4924: MatCheckPreallocated(mat, 1);
4925: PetscUseTypeMethod(mat, getrowmax, v, idx);
4926: }
4927: PetscObjectStateIncrease((PetscObject)v);
4928: return 0;
4929: }
4931: /*@C
4932: MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4933: row of the matrix
4935: Logically Collective on mat
4937: Input Parameter:
4938: . mat - the matrix
4940: Output Parameters:
4941: + v - the vector for storing the maximums
4942: - idx - the indices of the column found for each row (or NULL if not needed)
4944: Level: intermediate
4946: Notes:
4947: if a row is completely empty or has only 0.0 values then the idx[] value for that
4948: row is 0 (the first column).
4950: This code is only implemented for a couple of matrix formats.
4952: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4953: @*/
4954: PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
4955: {
4961: if (!mat->cmap->N) {
4962: VecSet(v, 0.0);
4963: if (idx) {
4964: PetscInt i, m = mat->rmap->n;
4965: for (i = 0; i < m; i++) idx[i] = -1;
4966: }
4967: } else {
4968: MatCheckPreallocated(mat, 1);
4969: if (idx) PetscArrayzero(idx, mat->rmap->n);
4970: PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
4971: }
4972: PetscObjectStateIncrease((PetscObject)v);
4973: return 0;
4974: }
4976: /*@
4977: MatGetRowSum - Gets the sum of each row of the matrix
4979: Logically or Neighborhood Collective on mat
4981: Input Parameters:
4982: . mat - the matrix
4984: Output Parameter:
4985: . v - the vector for storing the sum of rows
4987: Level: intermediate
4989: Notes:
4990: This code is slow since it is not currently specialized for different formats
4992: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
4993: @*/
4994: PetscErrorCode MatGetRowSum(Mat mat, Vec v)
4995: {
4996: Vec ones;
5002: MatCheckPreallocated(mat, 1);
5003: MatCreateVecs(mat, &ones, NULL);
5004: VecSet(ones, 1.);
5005: MatMult(mat, ones, v);
5006: VecDestroy(&ones);
5007: return 0;
5008: }
5010: /*@
5011: MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5012: when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5014: Collective on mat
5016: Input Parameter:
5017: . mat - the matrix to provide the transpose
5019: Output Parameter:
5020: . mat - 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
5022: Level: advanced
5024: Note:
5025: Normally he use of `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) requires that B was obtained with a call to `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B). This
5026: routine allows bypassing that call.
5028: .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5029: @*/
5030: PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5031: {
5032: PetscContainer rB = NULL;
5033: MatParentState *rb = NULL;
5035: PetscNew(&rb);
5036: rb->id = ((PetscObject)mat)->id;
5037: rb->state = 0;
5038: MatGetNonzeroState(mat, &rb->nonzerostate);
5039: PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB);
5040: PetscContainerSetPointer(rB, rb);
5041: PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault);
5042: PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB);
5043: PetscObjectDereference((PetscObject)rB);
5044: return 0;
5045: }
5047: /*@
5048: MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5050: Collective on mat
5052: Input Parameters:
5053: + mat - the matrix to transpose
5054: - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5056: Output Parameter:
5057: . B - the transpose
5059: Notes:
5060: If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5062: `MAT_REUSE_MATRIX` uses the B matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the
5063: transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5065: 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.
5067: Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5069: If mat is unchanged from the last call this function returns immediately without recomputing the result
5071: If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5073: Level: intermediate
5075: .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5076: `MatTransposeSymbolic()`
5077: @*/
5078: PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5079: {
5080: PetscContainer rB = NULL;
5081: MatParentState *rb = NULL;
5089: MatCheckPreallocated(mat, 1);
5090: if (reuse == MAT_REUSE_MATRIX) {
5091: PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5093: PetscContainerGetPointer(rB, (void **)&rb);
5095: if (rb->state == ((PetscObject)mat)->state) return 0;
5096: }
5098: PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0);
5099: if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5100: PetscUseTypeMethod(mat, transpose, reuse, B);
5101: PetscObjectStateIncrease((PetscObject)*B);
5102: }
5103: PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0);
5105: if (reuse == MAT_INITIAL_MATRIX) MatTransposeSetPrecursor(mat, *B);
5106: if (reuse != MAT_INPLACE_MATRIX) {
5107: PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5108: PetscContainerGetPointer(rB, (void **)&rb);
5109: rb->state = ((PetscObject)mat)->state;
5110: rb->nonzerostate = mat->nonzerostate;
5111: }
5112: return 0;
5113: }
5115: /*@
5116: MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5118: Collective on A
5120: Input Parameters:
5121: . A - the matrix to transpose
5123: Output Parameter:
5124: . 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
5125: numerical portion.
5127: Level: intermediate
5129: Note:
5130: This is not supported for many matrix types, use `MatTranspose()` in those cases
5132: .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5133: @*/
5134: PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5135: {
5141: PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0);
5142: (*A->ops->transposesymbolic)(A, B);
5143: PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0);
5145: MatTransposeSetPrecursor(A, *B);
5146: return 0;
5147: }
5149: PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5150: {
5151: PetscContainer rB;
5152: MatParentState *rb;
5158: PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB);
5160: PetscContainerGetPointer(rB, (void **)&rb);
5163: return 0;
5164: }
5166: /*@
5167: MatIsTranspose - Test whether a matrix is another one's transpose,
5168: or its own, in which case it tests symmetry.
5170: Collective on A
5172: Input Parameters:
5173: + A - the matrix to test
5174: - B - the matrix to test against, this can equal the first parameter
5176: Output Parameters:
5177: . flg - the result
5179: Notes:
5180: Only available for `MATAIJ` matrices.
5182: The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5183: test involves parallel copies of the block-offdiagonal parts of the matrix.
5185: Level: intermediate
5187: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5188: @*/
5189: PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5190: {
5191: PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5196: PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f);
5197: PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g);
5198: *flg = PETSC_FALSE;
5199: if (f && g) {
5201: (*f)(A, B, tol, flg);
5202: } else {
5203: MatType mattype;
5205: MatGetType(f ? B : A, &mattype);
5206: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5207: }
5208: return 0;
5209: }
5211: /*@
5212: MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5214: Collective on mat
5216: Input Parameters:
5217: + mat - the matrix to transpose and complex conjugate
5218: - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5220: Output Parameter:
5221: . B - the Hermitian transpose
5223: Level: intermediate
5225: .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5226: @*/
5227: PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5228: {
5229: MatTranspose(mat, reuse, B);
5230: #if defined(PETSC_USE_COMPLEX)
5231: MatConjugate(*B);
5232: #endif
5233: return 0;
5234: }
5236: /*@
5237: MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5239: Collective on A
5241: Input Parameters:
5242: + A - the matrix to test
5243: - B - the matrix to test against, this can equal the first parameter
5245: Output Parameters:
5246: . flg - the result
5248: Notes:
5249: Only available for `MATAIJ` matrices.
5251: The sequential algorithm
5252: has a running time of the order of the number of nonzeros; the parallel
5253: test involves parallel copies of the block-offdiagonal parts of the matrix.
5255: Level: intermediate
5257: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5258: @*/
5259: PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5260: {
5261: PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5266: PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f);
5267: PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g);
5268: if (f && g) {
5270: (*f)(A, B, tol, flg);
5271: }
5272: return 0;
5273: }
5275: /*@
5276: MatPermute - Creates a new matrix with rows and columns permuted from the
5277: original.
5279: Collective on mat
5281: Input Parameters:
5282: + mat - the matrix to permute
5283: . row - row permutation, each processor supplies only the permutation for its rows
5284: - col - column permutation, each processor supplies only the permutation for its columns
5286: Output Parameters:
5287: . B - the permuted matrix
5289: Level: advanced
5291: Note:
5292: The index sets map from row/col of permuted matrix to row/col of original matrix.
5293: The index sets should be on the same communicator as mat and have the same local sizes.
5295: Developer Note:
5296: If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5297: exploit the fact that row and col are permutations, consider implementing the
5298: more general `MatCreateSubMatrix()` instead.
5300: .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5301: @*/
5302: PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5303: {
5314: MatCheckPreallocated(mat, 1);
5316: if (mat->ops->permute) {
5317: PetscUseTypeMethod(mat, permute, row, col, B);
5318: PetscObjectStateIncrease((PetscObject)*B);
5319: } else {
5320: MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B);
5321: }
5322: return 0;
5323: }
5325: /*@
5326: MatEqual - Compares two matrices.
5328: Collective on A
5330: Input Parameters:
5331: + A - the first matrix
5332: - B - the second matrix
5334: Output Parameter:
5335: . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5337: Level: intermediate
5339: .seealso: `Mat`
5340: @*/
5341: PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5342: {
5349: MatCheckPreallocated(A, 1);
5350: MatCheckPreallocated(B, 2);
5354: B->cmap->N);
5355: if (A->ops->equal && A->ops->equal == B->ops->equal) {
5356: PetscUseTypeMethod(A, equal, B, flg);
5357: } else {
5358: MatMultEqual(A, B, 10, flg);
5359: }
5360: return 0;
5361: }
5363: /*@
5364: MatDiagonalScale - Scales a matrix on the left and right by diagonal
5365: matrices that are stored as vectors. Either of the two scaling
5366: matrices can be NULL.
5368: Collective on mat
5370: Input Parameters:
5371: + mat - the matrix to be scaled
5372: . l - the left scaling vector (or NULL)
5373: - r - the right scaling vector (or NULL)
5375: Note:
5376: `MatDiagonalScale()` computes A = LAR, where
5377: L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5378: The L scales the rows of the matrix, the R scales the columns of the matrix.
5380: Level: intermediate
5382: .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5383: @*/
5384: PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5385: {
5388: if (l) {
5391: }
5392: if (r) {
5395: }
5398: MatCheckPreallocated(mat, 1);
5399: if (!l && !r) return 0;
5401: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5402: PetscUseTypeMethod(mat, diagonalscale, l, r);
5403: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5404: PetscObjectStateIncrease((PetscObject)mat);
5405: if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5406: return 0;
5407: }
5409: /*@
5410: MatScale - Scales all elements of a matrix by a given number.
5412: Logically Collective on mat
5414: Input Parameters:
5415: + mat - the matrix to be scaled
5416: - a - the scaling value
5418: Output Parameter:
5419: . mat - the scaled matrix
5421: Level: intermediate
5423: .seealso: `Mat`, `MatDiagonalScale()`
5424: @*/
5425: PetscErrorCode MatScale(Mat mat, PetscScalar a)
5426: {
5433: MatCheckPreallocated(mat, 1);
5435: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5436: if (a != (PetscScalar)1.0) {
5437: PetscUseTypeMethod(mat, scale, a);
5438: PetscObjectStateIncrease((PetscObject)mat);
5439: }
5440: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5441: return 0;
5442: }
5444: /*@
5445: MatNorm - Calculates various norms of a matrix.
5447: Collective on mat
5449: Input Parameters:
5450: + mat - the matrix
5451: - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5453: Output Parameter:
5454: . nrm - the resulting norm
5456: Level: intermediate
5458: .seealso: `Mat`
5459: @*/
5460: PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5461: {
5468: MatCheckPreallocated(mat, 1);
5470: PetscUseTypeMethod(mat, norm, type, nrm);
5471: return 0;
5472: }
5474: /*
5475: This variable is used to prevent counting of MatAssemblyBegin() that
5476: are called from within a MatAssemblyEnd().
5477: */
5478: static PetscInt MatAssemblyEnd_InUse = 0;
5479: /*@
5480: MatAssemblyBegin - Begins assembling the matrix. This routine should
5481: be called after completing all calls to `MatSetValues()`.
5483: Collective on mat
5485: Input Parameters:
5486: + mat - the matrix
5487: - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5489: Notes:
5490: `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to
5491: use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5493: Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5494: in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5495: using the matrix.
5497: ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5498: 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
5499: a global collective operation requring all processes that share the matrix.
5501: Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5502: out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5503: before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5505: Level: beginner
5507: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5508: @*/
5509: PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5510: {
5513: MatCheckPreallocated(mat, 1);
5515: if (mat->assembled) {
5516: mat->was_assembled = PETSC_TRUE;
5517: mat->assembled = PETSC_FALSE;
5518: }
5520: if (!MatAssemblyEnd_InUse) {
5521: PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0);
5522: PetscTryTypeMethod(mat, assemblybegin, type);
5523: PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0);
5524: } else PetscTryTypeMethod(mat, assemblybegin, type);
5525: return 0;
5526: }
5528: /*@
5529: MatAssembled - Indicates if a matrix has been assembled and is ready for
5530: use; for example, in matrix-vector product.
5532: Not Collective
5534: Input Parameter:
5535: . mat - the matrix
5537: Output Parameter:
5538: . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5540: Level: advanced
5542: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5543: @*/
5544: PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5545: {
5548: *assembled = mat->assembled;
5549: return 0;
5550: }
5552: /*@
5553: MatAssemblyEnd - Completes assembling the matrix. This routine should
5554: be called after `MatAssemblyBegin()`.
5556: Collective on Mat
5558: Input Parameters:
5559: + mat - the matrix
5560: - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5562: Options Database Keys:
5563: + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5564: . -mat_view ::ascii_info_detail - Prints more detailed info
5565: . -mat_view - Prints matrix in ASCII format
5566: . -mat_view ::ascii_matlab - Prints matrix in Matlab format
5567: . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5568: . -display <name> - Sets display name (default is host)
5569: . -draw_pause <sec> - Sets number of seconds to pause after display
5570: . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5571: . -viewer_socket_machine <machine> - Machine to use for socket
5572: . -viewer_socket_port <port> - Port number to use for socket
5573: - -mat_view binary:filename[:append] - Save matrix to file in binary format
5575: Level: beginner
5577: .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5578: @*/
5579: PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5580: {
5581: static PetscInt inassm = 0;
5582: PetscBool flg = PETSC_FALSE;
5587: inassm++;
5588: MatAssemblyEnd_InUse++;
5589: if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5590: PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0);
5591: PetscTryTypeMethod(mat, assemblyend, type);
5592: PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0);
5593: } else PetscTryTypeMethod(mat, assemblyend, type);
5595: /* Flush assembly is not a true assembly */
5596: if (type != MAT_FLUSH_ASSEMBLY) {
5597: if (mat->num_ass) {
5598: if (!mat->symmetry_eternal) {
5599: mat->symmetric = PETSC_BOOL3_UNKNOWN;
5600: mat->hermitian = PETSC_BOOL3_UNKNOWN;
5601: }
5602: if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5603: if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5604: }
5605: mat->num_ass++;
5606: mat->assembled = PETSC_TRUE;
5607: mat->ass_nonzerostate = mat->nonzerostate;
5608: }
5610: mat->insertmode = NOT_SET_VALUES;
5611: MatAssemblyEnd_InUse--;
5612: PetscObjectStateIncrease((PetscObject)mat);
5613: if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5614: MatViewFromOptions(mat, NULL, "-mat_view");
5616: if (mat->checksymmetryonassembly) {
5617: MatIsSymmetric(mat, mat->checksymmetrytol, &flg);
5618: if (flg) {
5619: PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5620: } else {
5621: PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5622: }
5623: }
5624: if (mat->nullsp && mat->checknullspaceonassembly) MatNullSpaceTest(mat->nullsp, mat, NULL);
5625: }
5626: inassm--;
5627: return 0;
5628: }
5630: /*@
5631: MatSetOption - Sets a parameter option for a matrix. Some options
5632: may be specific to certain storage formats. Some options
5633: determine how values will be inserted (or added). Sorted,
5634: row-oriented input will generally assemble the fastest. The default
5635: is row-oriented.
5637: Logically Collective on mat for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5639: Input Parameters:
5640: + mat - the matrix
5641: . option - the option, one of those listed below (and possibly others),
5642: - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5644: Options Describing Matrix Structure:
5645: + `MAT_SPD` - symmetric positive definite
5646: . `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5647: . `MAT_HERMITIAN` - transpose is the complex conjugation
5648: . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5649: . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5650: . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5651: - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5653: These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5654: do not need to be computed (usually at a high cost)
5656: Options For Use with `MatSetValues()`:
5657: Insert a logically dense subblock, which can be
5658: . `MAT_ROW_ORIENTED` - row-oriented (default)
5660: Note these options reflect the data you pass in with `MatSetValues()`; it has
5661: nothing to do with how the data is stored internally in the matrix
5662: data structure.
5664: When (re)assembling a matrix, we can restrict the input for
5665: efficiency/debugging purposes. These options include
5666: + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5667: . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5668: . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5669: . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5670: . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5671: . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5672: any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5673: performance for very large process counts.
5674: - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5675: of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5676: functions, instead sending only neighbor messages.
5678: Notes:
5679: Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5681: Some options are relevant only for particular matrix types and
5682: are thus ignored by others. Other options are not supported by
5683: certain matrix types and will generate an error message if set.
5685: If using a Fortran 77 module to compute a matrix, one may need to
5686: use the column-oriented option (or convert to the row-oriented
5687: format).
5689: `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5690: that would generate a new entry in the nonzero structure is instead
5691: ignored. Thus, if memory has not alredy been allocated for this particular
5692: data, then the insertion is ignored. For dense matrices, in which
5693: the entire array is allocated, no entries are ever ignored.
5694: Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5696: `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5697: that would generate a new entry in the nonzero structure instead produces
5698: 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
5700: `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5701: that would generate a new entry that has not been preallocated will
5702: instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5703: only.) This is a useful flag when debugging matrix memory preallocation.
5704: If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5706: `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5707: other processors should be dropped, rather than stashed.
5708: This is useful if you know that the "owning" processor is also
5709: always generating the correct matrix entries, so that PETSc need
5710: not transfer duplicate entries generated on another processor.
5712: `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5713: searches during matrix assembly. When this flag is set, the hash table
5714: is created during the first matrix assembly. This hash table is
5715: used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5716: to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5717: should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5718: supported by` MATMPIBAIJ` format only.
5720: `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5721: are kept in the nonzero structure
5723: `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5724: a zero location in the matrix
5726: `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5728: `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5729: zero row routines and thus improves performance for very large process counts.
5731: `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5732: part of the matrix (since they should match the upper triangular part).
5734: `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5735: single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5736: with finite difference schemes with non-periodic boundary conditions.
5738: Developer Note:
5739: `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5740: places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5741: to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5742: not changed.
5744: Level: intermediate
5746: .seealso: `MatOption`, `Mat`, `MatGetOption()`
5747: @*/
5748: PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5749: {
5751: if (op > 0) {
5754: }
5758: switch (op) {
5759: case MAT_FORCE_DIAGONAL_ENTRIES:
5760: mat->force_diagonals = flg;
5761: return 0;
5762: case MAT_NO_OFF_PROC_ENTRIES:
5763: mat->nooffprocentries = flg;
5764: return 0;
5765: case MAT_SUBSET_OFF_PROC_ENTRIES:
5766: mat->assembly_subset = flg;
5767: if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5768: #if !defined(PETSC_HAVE_MPIUNI)
5769: MatStashScatterDestroy_BTS(&mat->stash);
5770: #endif
5771: mat->stash.first_assembly_done = PETSC_FALSE;
5772: }
5773: return 0;
5774: case MAT_NO_OFF_PROC_ZERO_ROWS:
5775: mat->nooffproczerorows = flg;
5776: return 0;
5777: case MAT_SPD:
5778: if (flg) {
5779: mat->spd = PETSC_BOOL3_TRUE;
5780: mat->symmetric = PETSC_BOOL3_TRUE;
5781: mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5782: } else {
5783: mat->spd = PETSC_BOOL3_FALSE;
5784: }
5785: break;
5786: case MAT_SYMMETRIC:
5787: mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5788: if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5789: #if !defined(PETSC_USE_COMPLEX)
5790: mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5791: #endif
5792: break;
5793: case MAT_HERMITIAN:
5794: mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5795: if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5796: #if !defined(PETSC_USE_COMPLEX)
5797: mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5798: #endif
5799: break;
5800: case MAT_STRUCTURALLY_SYMMETRIC:
5801: mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5802: break;
5803: case MAT_SYMMETRY_ETERNAL:
5805: mat->symmetry_eternal = flg;
5806: if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5807: break;
5808: case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5810: mat->structural_symmetry_eternal = flg;
5811: break;
5812: case MAT_SPD_ETERNAL:
5814: mat->spd_eternal = flg;
5815: if (flg) {
5816: mat->structural_symmetry_eternal = PETSC_TRUE;
5817: mat->symmetry_eternal = PETSC_TRUE;
5818: }
5819: break;
5820: case MAT_STRUCTURE_ONLY:
5821: mat->structure_only = flg;
5822: break;
5823: case MAT_SORTED_FULL:
5824: mat->sortedfull = flg;
5825: break;
5826: default:
5827: break;
5828: }
5829: PetscTryTypeMethod(mat, setoption, op, flg);
5830: return 0;
5831: }
5833: /*@
5834: MatGetOption - Gets a parameter option that has been set for a matrix.
5836: Logically Collective on mat
5838: Input Parameters:
5839: + mat - the matrix
5840: - option - the option, this only responds to certain options, check the code for which ones
5842: Output Parameter:
5843: . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5845: Notes:
5846: Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5848: Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5849: `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5851: Level: intermediate
5853: .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5854: `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5855: @*/
5856: PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5857: {
5864: switch (op) {
5865: case MAT_NO_OFF_PROC_ENTRIES:
5866: *flg = mat->nooffprocentries;
5867: break;
5868: case MAT_NO_OFF_PROC_ZERO_ROWS:
5869: *flg = mat->nooffproczerorows;
5870: break;
5871: case MAT_SYMMETRIC:
5872: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5873: break;
5874: case MAT_HERMITIAN:
5875: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5876: break;
5877: case MAT_STRUCTURALLY_SYMMETRIC:
5878: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5879: break;
5880: case MAT_SPD:
5881: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
5882: break;
5883: case MAT_SYMMETRY_ETERNAL:
5884: *flg = mat->symmetry_eternal;
5885: break;
5886: case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5887: *flg = mat->symmetry_eternal;
5888: break;
5889: default:
5890: break;
5891: }
5892: return 0;
5893: }
5895: /*@
5896: MatZeroEntries - Zeros all entries of a matrix. For sparse matrices
5897: this routine retains the old nonzero structure.
5899: Logically Collective on mat
5901: Input Parameters:
5902: . mat - the matrix
5904: Level: intermediate
5906: Note:
5907: 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.
5908: See the Performance chapter of the users manual for information on preallocating matrices.
5910: .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
5911: @*/
5912: PetscErrorCode MatZeroEntries(Mat mat)
5913: {
5918: MatCheckPreallocated(mat, 1);
5920: PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0);
5921: PetscUseTypeMethod(mat, zeroentries);
5922: PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0);
5923: PetscObjectStateIncrease((PetscObject)mat);
5924: return 0;
5925: }
5927: /*@
5928: MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5929: of a set of rows and columns of a matrix.
5931: Collective on mat
5933: Input Parameters:
5934: + mat - the matrix
5935: . numRows - the number of rows to remove
5936: . rows - the global row indices
5937: . diag - value put in the diagonal of the eliminated rows
5938: . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5939: - b - optional vector of right hand side, that will be adjusted by provided solution
5941: Notes:
5942: This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5944: For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5945: 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
5947: If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5948: Krylov method to take advantage of the known solution on the zeroed rows.
5950: For the parallel case, all processes that share the matrix (i.e.,
5951: those in the communicator used for matrix creation) MUST call this
5952: routine, regardless of whether any rows being zeroed are owned by
5953: them.
5955: Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5957: Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5958: list only rows local to itself).
5960: The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
5962: Level: intermediate
5964: .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5965: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5966: @*/
5967: PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
5968: {
5974: MatCheckPreallocated(mat, 1);
5976: PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
5977: MatViewFromOptions(mat, NULL, "-mat_view");
5978: PetscObjectStateIncrease((PetscObject)mat);
5979: return 0;
5980: }
5982: /*@
5983: MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5984: of a set of rows and columns of a matrix.
5986: Collective on mat
5988: Input Parameters:
5989: + mat - the matrix
5990: . is - the rows to zero
5991: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5992: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5993: - b - optional vector of right hand side, that will be adjusted by provided solution
5995: Note:
5996: See `MatZeroRowsColumns()` for details on how this routine operates.
5998: Level: intermediate
6000: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6001: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6002: @*/
6003: PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6004: {
6005: PetscInt numRows;
6006: const PetscInt *rows;
6012: ISGetLocalSize(is, &numRows);
6013: ISGetIndices(is, &rows);
6014: MatZeroRowsColumns(mat, numRows, rows, diag, x, b);
6015: ISRestoreIndices(is, &rows);
6016: return 0;
6017: }
6019: /*@
6020: MatZeroRows - Zeros all entries (except possibly the main diagonal)
6021: of a set of rows of a matrix.
6023: Collective on mat
6025: Input Parameters:
6026: + mat - the matrix
6027: . numRows - the number of rows to remove
6028: . rows - the global row indices
6029: . diag - value put in the diagonal of the eliminated rows
6030: . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6031: - b - optional vector of right hand side, that will be adjusted by provided solution
6033: Notes:
6034: This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6036: For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6038: If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6039: Krylov method to take advantage of the known solution on the zeroed rows.
6041: May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reducing problem (after completely eliminating the zeroed rows and their corresponding columns)
6042: from the matrix.
6044: Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6045: but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal
6046: formats this does not alter the nonzero structure.
6048: If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6049: of the matrix is not changed the values are
6050: merely zeroed.
6052: The user can set a value in the diagonal entry (or for the `MATAIJ` format
6053: formats can optionally remove the main diagonal entry from the
6054: nonzero structure as well, by passing 0.0 as the final argument).
6056: For the parallel case, all processes that share the matrix (i.e.,
6057: those in the communicator used for matrix creation) MUST call this
6058: routine, regardless of whether any rows being zeroed are owned by
6059: them.
6061: Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6062: list only rows local to itself).
6064: You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6065: owns that are to be zeroed. This saves a global synchronization in the implementation.
6067: Level: intermediate
6069: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6070: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6071: @*/
6072: PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6073: {
6079: MatCheckPreallocated(mat, 1);
6081: PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6082: MatViewFromOptions(mat, NULL, "-mat_view");
6083: PetscObjectStateIncrease((PetscObject)mat);
6084: return 0;
6085: }
6087: /*@
6088: MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6089: of a set of rows of a matrix.
6091: Collective on Mat
6093: Input Parameters:
6094: + mat - the matrix
6095: . is - index set of rows to remove (if NULL then no row is removed)
6096: . diag - value put in all diagonals of eliminated rows
6097: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6098: - b - optional vector of right hand side, that will be adjusted by provided solution
6100: Note:
6101: See `MatZeroRows()` for details on how this routine operates.
6103: Level: intermediate
6105: .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6106: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6107: @*/
6108: PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6109: {
6110: PetscInt numRows = 0;
6111: const PetscInt *rows = NULL;
6115: if (is) {
6117: ISGetLocalSize(is, &numRows);
6118: ISGetIndices(is, &rows);
6119: }
6120: MatZeroRows(mat, numRows, rows, diag, x, b);
6121: if (is) ISRestoreIndices(is, &rows);
6122: return 0;
6123: }
6125: /*@
6126: MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6127: of a set of rows of a matrix. These rows must be local to the process.
6129: Collective on mat
6131: Input Parameters:
6132: + mat - the matrix
6133: . numRows - the number of rows to remove
6134: . rows - the grid coordinates (and component number when dof > 1) for matrix rows
6135: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6136: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6137: - b - optional vector of right hand side, that will be adjusted by provided solution
6139: Notes:
6140: See `MatZeroRows()` for details on how this routine operates.
6142: The grid coordinates are across the entire grid, not just the local portion
6144: In Fortran idxm and idxn should be declared as
6145: $ MatStencil idxm(4,m)
6146: and the values inserted using
6147: $ idxm(MatStencil_i,1) = i
6148: $ idxm(MatStencil_j,1) = j
6149: $ idxm(MatStencil_k,1) = k
6150: $ idxm(MatStencil_c,1) = c
6151: etc
6153: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6154: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6155: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6156: `DM_BOUNDARY_PERIODIC` boundary type.
6158: 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
6159: a single value per point) you can skip filling those indices.
6161: Level: intermediate
6163: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6164: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6165: @*/
6166: PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6167: {
6168: PetscInt dim = mat->stencil.dim;
6169: PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc);
6170: PetscInt *dims = mat->stencil.dims + 1;
6171: PetscInt *starts = mat->stencil.starts;
6172: PetscInt *dxm = (PetscInt *)rows;
6173: PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6179: PetscMalloc1(numRows, &jdxm);
6180: for (i = 0; i < numRows; ++i) {
6181: /* Skip unused dimensions (they are ordered k, j, i, c) */
6182: for (j = 0; j < 3 - sdim; ++j) dxm++;
6183: /* Local index in X dir */
6184: tmp = *dxm++ - starts[0];
6185: /* Loop over remaining dimensions */
6186: for (j = 0; j < dim - 1; ++j) {
6187: /* If nonlocal, set index to be negative */
6188: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6189: /* Update local index */
6190: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6191: }
6192: /* Skip component slot if necessary */
6193: if (mat->stencil.noc) dxm++;
6194: /* Local row number */
6195: if (tmp >= 0) jdxm[numNewRows++] = tmp;
6196: }
6197: MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b);
6198: PetscFree(jdxm);
6199: return 0;
6200: }
6202: /*@
6203: MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6204: of a set of rows and columns of a matrix.
6206: Collective on mat
6208: Input Parameters:
6209: + mat - the matrix
6210: . numRows - the number of rows/columns to remove
6211: . rows - the grid coordinates (and component number when dof > 1) for matrix rows
6212: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6213: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6214: - b - optional vector of right hand side, that will be adjusted by provided solution
6216: Notes:
6217: See `MatZeroRowsColumns()` for details on how this routine operates.
6219: The grid coordinates are across the entire grid, not just the local portion
6221: In Fortran idxm and idxn should be declared as
6222: $ MatStencil idxm(4,m)
6223: and the values inserted using
6224: $ idxm(MatStencil_i,1) = i
6225: $ idxm(MatStencil_j,1) = j
6226: $ idxm(MatStencil_k,1) = k
6227: $ idxm(MatStencil_c,1) = c
6228: etc
6230: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6231: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6232: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6233: `DM_BOUNDARY_PERIODIC` boundary type.
6235: 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
6236: a single value per point) you can skip filling those indices.
6238: Level: intermediate
6240: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6241: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6242: @*/
6243: PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6244: {
6245: PetscInt dim = mat->stencil.dim;
6246: PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc);
6247: PetscInt *dims = mat->stencil.dims + 1;
6248: PetscInt *starts = mat->stencil.starts;
6249: PetscInt *dxm = (PetscInt *)rows;
6250: PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6256: PetscMalloc1(numRows, &jdxm);
6257: for (i = 0; i < numRows; ++i) {
6258: /* Skip unused dimensions (they are ordered k, j, i, c) */
6259: for (j = 0; j < 3 - sdim; ++j) dxm++;
6260: /* Local index in X dir */
6261: tmp = *dxm++ - starts[0];
6262: /* Loop over remaining dimensions */
6263: for (j = 0; j < dim - 1; ++j) {
6264: /* If nonlocal, set index to be negative */
6265: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6266: /* Update local index */
6267: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6268: }
6269: /* Skip component slot if necessary */
6270: if (mat->stencil.noc) dxm++;
6271: /* Local row number */
6272: if (tmp >= 0) jdxm[numNewRows++] = tmp;
6273: }
6274: MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b);
6275: PetscFree(jdxm);
6276: return 0;
6277: }
6279: /*@C
6280: MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6281: of a set of rows of a matrix; using local numbering of rows.
6283: Collective on mat
6285: Input Parameters:
6286: + mat - the matrix
6287: . numRows - the number of rows to remove
6288: . rows - the local row indices
6289: . diag - value put in all diagonals of eliminated rows
6290: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6291: - b - optional vector of right hand side, that will be adjusted by provided solution
6293: Notes:
6294: Before calling `MatZeroRowsLocal()`, the user must first set the
6295: local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6297: See `MatZeroRows()` for details on how this routine operates.
6299: Level: intermediate
6301: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6302: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6303: @*/
6304: PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6305: {
6311: MatCheckPreallocated(mat, 1);
6313: if (mat->ops->zerorowslocal) {
6314: PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6315: } else {
6316: IS is, newis;
6317: const PetscInt *newRows;
6320: ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6321: ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis);
6322: ISGetIndices(newis, &newRows);
6323: PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6324: ISRestoreIndices(newis, &newRows);
6325: ISDestroy(&newis);
6326: ISDestroy(&is);
6327: }
6328: PetscObjectStateIncrease((PetscObject)mat);
6329: return 0;
6330: }
6332: /*@
6333: MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6334: of a set of rows of a matrix; using local numbering of rows.
6336: Collective on mat
6338: Input Parameters:
6339: + mat - the matrix
6340: . is - index set of rows to remove
6341: . diag - value put in all diagonals of eliminated rows
6342: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6343: - b - optional vector of right hand side, that will be adjusted by provided solution
6345: Notes:
6346: Before calling `MatZeroRowsLocalIS()`, the user must first set the
6347: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6349: See `MatZeroRows()` for details on how this routine operates.
6351: Level: intermediate
6353: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6354: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6355: @*/
6356: PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6357: {
6358: PetscInt numRows;
6359: const PetscInt *rows;
6366: MatCheckPreallocated(mat, 1);
6368: ISGetLocalSize(is, &numRows);
6369: ISGetIndices(is, &rows);
6370: MatZeroRowsLocal(mat, numRows, rows, diag, x, b);
6371: ISRestoreIndices(is, &rows);
6372: return 0;
6373: }
6375: /*@
6376: MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6377: of a set of rows and columns of a matrix; using local numbering of rows.
6379: Collective on mat
6381: Input Parameters:
6382: + mat - the matrix
6383: . numRows - the number of rows to remove
6384: . rows - the global row indices
6385: . diag - value put in all diagonals of eliminated rows
6386: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6387: - b - optional vector of right hand side, that will be adjusted by provided solution
6389: Notes:
6390: Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6391: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6393: See `MatZeroRowsColumns()` for details on how this routine operates.
6395: Level: intermediate
6397: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6398: `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6399: @*/
6400: PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6401: {
6402: IS is, newis;
6403: const PetscInt *newRows;
6410: MatCheckPreallocated(mat, 1);
6413: ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6414: ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis);
6415: ISGetIndices(newis, &newRows);
6416: PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6417: ISRestoreIndices(newis, &newRows);
6418: ISDestroy(&newis);
6419: ISDestroy(&is);
6420: PetscObjectStateIncrease((PetscObject)mat);
6421: return 0;
6422: }
6424: /*@
6425: MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6426: of a set of rows and columns of a matrix; using local numbering of rows.
6428: Collective on Mat
6430: Input Parameters:
6431: + mat - the matrix
6432: . is - index set of rows to remove
6433: . diag - value put in all diagonals of eliminated rows
6434: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6435: - b - optional vector of right hand side, that will be adjusted by provided solution
6437: Notes:
6438: Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6439: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6441: See `MatZeroRowsColumns()` for details on how this routine operates.
6443: Level: intermediate
6445: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6446: `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6447: @*/
6448: PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6449: {
6450: PetscInt numRows;
6451: const PetscInt *rows;
6458: MatCheckPreallocated(mat, 1);
6460: ISGetLocalSize(is, &numRows);
6461: ISGetIndices(is, &rows);
6462: MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b);
6463: ISRestoreIndices(is, &rows);
6464: return 0;
6465: }
6467: /*@C
6468: MatGetSize - Returns the numbers of rows and columns in a matrix.
6470: Not Collective
6472: Input Parameter:
6473: . mat - the matrix
6475: Output Parameters:
6476: + m - the number of global rows
6477: - n - the number of global columns
6479: Note: both output parameters can be NULL on input.
6481: Level: beginner
6483: .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6484: @*/
6485: PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6486: {
6488: if (m) *m = mat->rmap->N;
6489: if (n) *n = mat->cmap->N;
6490: return 0;
6491: }
6493: /*@C
6494: MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6495: of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6497: Not Collective
6499: Input Parameter:
6500: . mat - the matrix
6502: Output Parameters:
6503: + m - the number of local rows, use `NULL` to not obtain this value
6504: - n - the number of local columns, use `NULL` to not obtain this value
6506: Level: beginner
6508: .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6509: @*/
6510: PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6511: {
6515: if (m) *m = mat->rmap->n;
6516: if (n) *n = mat->cmap->n;
6517: return 0;
6518: }
6520: /*@C
6521: MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6522: this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6524: Not Collective, unless matrix has not been allocated, then collective on mat
6526: Input Parameter:
6527: . mat - the matrix
6529: Output Parameters:
6530: + m - the global index of the first local column, use `NULL` to not obtain this value
6531: - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6533: Level: developer
6535: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6536: @*/
6537: PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6538: {
6543: MatCheckPreallocated(mat, 1);
6544: if (m) *m = mat->cmap->rstart;
6545: if (n) *n = mat->cmap->rend;
6546: return 0;
6547: }
6549: /*@C
6550: MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6551: this MPI rank. For all matrices it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6552: vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6554: Not Collective
6556: Input Parameter:
6557: . mat - the matrix
6559: Output Parameters:
6560: + m - the global index of the first local row, use `NULL` to not obtain this value
6561: - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6563: Note:
6564: This function requires that the matrix be preallocated. If you have not preallocated, consider using
6565: `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6566: and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6568: Level: beginner
6570: .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6571: `PetscLayout`
6572: @*/
6573: PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6574: {
6579: MatCheckPreallocated(mat, 1);
6580: if (m) *m = mat->rmap->rstart;
6581: if (n) *n = mat->rmap->rend;
6582: return 0;
6583: }
6585: /*@C
6586: MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6587: each process. For all matrices it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix
6588: vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6590: Not Collective, unless matrix has not been allocated, then collective on mat
6592: Input Parameters:
6593: . mat - the matrix
6595: Output Parameters:
6596: . ranges - start of each processors portion plus one more than the total length at the end
6598: Level: beginner
6600: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6601: @*/
6602: PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6603: {
6606: MatCheckPreallocated(mat, 1);
6607: PetscLayoutGetRanges(mat->rmap, ranges);
6608: return 0;
6609: }
6611: /*@C
6612: MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6613: each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6615: Not Collective, unless matrix has not been allocated, then collective on Mat
6617: Input Parameters:
6618: . mat - the matrix
6620: Output Parameters:
6621: . ranges - start of each processors portion plus one more then the total length at the end
6623: Level: beginner
6625: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6626: @*/
6627: PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6628: {
6631: MatCheckPreallocated(mat, 1);
6632: PetscLayoutGetRanges(mat->cmap, ranges);
6633: return 0;
6634: }
6636: /*@C
6637: MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6638: corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6639: is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6641: Not Collective
6643: Input Parameter:
6644: . A - matrix
6646: Output Parameters:
6647: + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6648: - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6650: Level: intermediate
6652: .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6653: @*/
6654: PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6655: {
6656: PetscErrorCode (*f)(Mat, IS *, IS *);
6658: MatCheckPreallocated(A, 1);
6659: PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f);
6660: if (f) {
6661: (*f)(A, rows, cols);
6662: } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6663: if (rows) ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows);
6664: if (cols) ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols);
6665: }
6666: return 0;
6667: }
6669: /*@C
6670: MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6671: Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6672: to complete the factorization.
6674: Collective on fact
6676: Input Parameters:
6677: + fact - the factorized matrix obtained with `MatGetFactor()`
6678: . mat - the matrix
6679: . row - row permutation
6680: . column - column permutation
6681: - info - structure containing
6682: $ levels - number of levels of fill.
6683: $ expected fill - as ratio of original fill.
6684: $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6685: missing diagonal entries)
6687: Output Parameters:
6688: . fact - new matrix that has been symbolically factored
6690: Level: developer
6692: Notes:
6693: See [Matrix Factorization](sec_matfactor) for additional information.
6695: Most users should employ the `KSP` interface for linear solvers
6696: instead of working directly with matrix algebra routines such as this.
6697: See, e.g., `KSPCreate()`.
6699: Uses the definition of level of fill as in Y. Saad, 2003
6701: Developer Note:
6702: The Fortran interface is not autogenerated as the f90
6703: interface definition cannot be generated correctly [due to `MatFactorInfo`]
6705: References:
6706: . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6708: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6709: `MatGetOrdering()`, `MatFactorInfo`
6710: @*/
6711: PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6712: {
6721: if (!fact->ops->ilufactorsymbolic) {
6722: MatSolverType stype;
6723: MatFactorGetSolverType(fact, &stype);
6724: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6725: }
6728: MatCheckPreallocated(mat, 2);
6730: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0);
6731: (fact->ops->ilufactorsymbolic)(fact, mat, row, col, info);
6732: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0);
6733: return 0;
6734: }
6736: /*@C
6737: MatICCFactorSymbolic - Performs symbolic incomplete
6738: Cholesky factorization for a symmetric matrix. Use
6739: `MatCholeskyFactorNumeric()` to complete the factorization.
6741: Collective on fact
6743: Input Parameters:
6744: + fact - the factorized matrix obtained with `MatGetFactor()`
6745: . mat - the matrix to be factored
6746: . perm - row and column permutation
6747: - info - structure containing
6748: $ levels - number of levels of fill.
6749: $ expected fill - as ratio of original fill.
6751: Output Parameter:
6752: . fact - the factored matrix
6754: Level: developer
6756: Notes:
6757: Most users should employ the `KSP` interface for linear solvers
6758: instead of working directly with matrix algebra routines such as this.
6759: See, e.g., `KSPCreate()`.
6761: This uses the definition of level of fill as in Y. Saad, 2003
6763: Developer Note:
6764: The Fortran interface is not autogenerated as the f90
6765: interface definition cannot be generated correctly [due to `MatFactorInfo`]
6767: References:
6768: . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6770: .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6771: @*/
6772: PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6773: {
6782: if (!(fact)->ops->iccfactorsymbolic) {
6783: MatSolverType stype;
6784: MatFactorGetSolverType(fact, &stype);
6785: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6786: }
6788: MatCheckPreallocated(mat, 2);
6790: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6791: (fact->ops->iccfactorsymbolic)(fact, mat, perm, info);
6792: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6793: return 0;
6794: }
6796: /*@C
6797: MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6798: points to an array of valid matrices, they may be reused to store the new
6799: submatrices.
6801: Collective on mat
6803: Input Parameters:
6804: + mat - the matrix
6805: . n - the number of submatrixes to be extracted (on this processor, may be zero)
6806: . irow, icol - index sets of rows and columns to extract
6807: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6809: Output Parameter:
6810: . submat - the array of submatrices
6812: Notes:
6813: `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6814: (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6815: to extract a parallel submatrix.
6817: Some matrix types place restrictions on the row and column
6818: indices, such as that they be sorted or that they be equal to each other.
6820: The index sets may not have duplicate entries.
6822: When extracting submatrices from a parallel matrix, each processor can
6823: form a different submatrix by setting the rows and columns of its
6824: individual index sets according to the local submatrix desired.
6826: When finished using the submatrices, the user should destroy
6827: them with `MatDestroySubMatrices()`.
6829: `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6830: original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6832: This routine creates the matrices in submat; you should NOT create them before
6833: calling it. It also allocates the array of matrix pointers submat.
6835: For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6836: request one row/column in a block, they must request all rows/columns that are in
6837: that block. For example, if the block size is 2 you cannot request just row 0 and
6838: column 0.
6840: Fortran Note:
6841: The Fortran interface is slightly different from that given below; it
6842: requires one to pass in as submat a `Mat` (integer) array of size at least n+1.
6844: Level: advanced
6846: .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6847: @*/
6848: PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6849: {
6850: PetscInt i;
6851: PetscBool eq;
6855: if (n) {
6860: }
6862: if (n && scall == MAT_REUSE_MATRIX) {
6865: }
6868: MatCheckPreallocated(mat, 1);
6869: PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6870: PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6871: PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6872: for (i = 0; i < n; i++) {
6873: (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6874: ISEqualUnsorted(irow[i], icol[i], &eq);
6875: if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6876: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
6877: if (mat->boundtocpu && mat->bindingpropagates) {
6878: MatBindToCPU((*submat)[i], PETSC_TRUE);
6879: MatSetBindingPropagates((*submat)[i], PETSC_TRUE);
6880: }
6881: #endif
6882: }
6883: return 0;
6884: }
6886: /*@C
6887: MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
6889: Collective on mat
6891: Input Parameters:
6892: + mat - the matrix
6893: . n - the number of submatrixes to be extracted
6894: . irow, icol - index sets of rows and columns to extract
6895: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6897: Output Parameter:
6898: . submat - the array of submatrices
6900: Level: advanced
6902: Note:
6903: This is used by `PCGASM`
6905: .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6906: @*/
6907: PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6908: {
6909: PetscInt i;
6910: PetscBool eq;
6914: if (n) {
6919: }
6921: if (n && scall == MAT_REUSE_MATRIX) {
6924: }
6927: MatCheckPreallocated(mat, 1);
6929: PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6930: PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6931: PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6932: for (i = 0; i < n; i++) {
6933: ISEqualUnsorted(irow[i], icol[i], &eq);
6934: if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6935: }
6936: return 0;
6937: }
6939: /*@C
6940: MatDestroyMatrices - Destroys an array of matrices.
6942: Collective on mat
6944: Input Parameters:
6945: + n - the number of local matrices
6946: - mat - the matrices (note that this is a pointer to the array of matrices)
6948: Level: advanced
6950: Note:
6951: Frees not only the matrices, but also the array that contains the matrices
6952: In Fortran will not free the array.
6954: .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6955: @*/
6956: PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
6957: {
6958: PetscInt i;
6960: if (!*mat) return 0;
6964: for (i = 0; i < n; i++) MatDestroy(&(*mat)[i]);
6966: /* memory is allocated even if n = 0 */
6967: PetscFree(*mat);
6968: return 0;
6969: }
6971: /*@C
6972: MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
6974: Collective on mat
6976: Input Parameters:
6977: + n - the number of local matrices
6978: - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
6979: sequence of MatCreateSubMatrices())
6981: Level: advanced
6983: Note:
6984: Frees not only the matrices, but also the array that contains the matrices
6985: In Fortran will not free the array.
6987: .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6988: @*/
6989: PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
6990: {
6991: Mat mat0;
6993: if (!*mat) return 0;
6994: /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
6998: mat0 = (*mat)[0];
6999: if (mat0 && mat0->ops->destroysubmatrices) {
7000: (mat0->ops->destroysubmatrices)(n, mat);
7001: } else {
7002: MatDestroyMatrices(n, mat);
7003: }
7004: return 0;
7005: }
7007: /*@C
7008: MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7010: Collective on mat
7012: Input Parameters:
7013: . mat - the matrix
7015: Output Parameter:
7016: . matstruct - the sequential matrix with the nonzero structure of mat
7018: Level: developer
7020: .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7021: @*/
7022: PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7023: {
7029: MatCheckPreallocated(mat, 1);
7031: PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7032: PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7033: PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7034: return 0;
7035: }
7037: /*@C
7038: MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7040: Collective on mat
7042: Input Parameters:
7043: . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7044: sequence of `MatGetSequentialNonzeroStructure()`)
7046: Level: advanced
7048: Note:
7049: Frees not only the matrices, but also the array that contains the matrices
7051: .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7052: @*/
7053: PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7054: {
7056: MatDestroy(mat);
7057: return 0;
7058: }
7060: /*@
7061: MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7062: replaces the index sets by larger ones that represent submatrices with
7063: additional overlap.
7065: Collective on mat
7067: Input Parameters:
7068: + mat - the matrix
7069: . n - the number of index sets
7070: . is - the array of index sets (these index sets will changed during the call)
7071: - ov - the additional overlap requested
7073: Options Database:
7074: . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7076: Level: developer
7078: Developer Note:
7079: Any implementation must preserve block sizes. That is: if the row block size and the column block size of mat are equal to bs, then the output index sets must be compatible with bs.
7081: .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7082: @*/
7083: PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7084: {
7085: PetscInt i, bs, cbs;
7091: if (n) {
7094: }
7097: MatCheckPreallocated(mat, 1);
7099: if (!ov || !n) return 0;
7100: PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7101: PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7102: PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7103: MatGetBlockSizes(mat, &bs, &cbs);
7104: if (bs == cbs) {
7105: for (i = 0; i < n; i++) ISSetBlockSize(is[i], bs);
7106: }
7107: return 0;
7108: }
7110: PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7112: /*@
7113: MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7114: a sub communicator, replaces the index sets by larger ones that represent submatrices with
7115: additional overlap.
7117: Collective on mat
7119: Input Parameters:
7120: + mat - the matrix
7121: . n - the number of index sets
7122: . is - the array of index sets (these index sets will changed during the call)
7123: - ov - the additional overlap requested
7125: ` Options Database:
7126: . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7128: Level: developer
7130: .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7131: @*/
7132: PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7133: {
7134: PetscInt i;
7139: if (n) {
7142: }
7145: MatCheckPreallocated(mat, 1);
7146: if (!ov) return 0;
7147: PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7148: for (i = 0; i < n; i++) MatIncreaseOverlapSplit_Single(mat, &is[i], ov);
7149: PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7150: return 0;
7151: }
7153: /*@
7154: MatGetBlockSize - Returns the matrix block size.
7156: Not Collective
7158: Input Parameter:
7159: . mat - the matrix
7161: Output Parameter:
7162: . bs - block size
7164: Notes:
7165: Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7167: If the block size has not been set yet this routine returns 1.
7169: Level: intermediate
7171: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7172: @*/
7173: PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7174: {
7177: *bs = PetscAbs(mat->rmap->bs);
7178: return 0;
7179: }
7181: /*@
7182: MatGetBlockSizes - Returns the matrix block row and column sizes.
7184: Not Collective
7186: Input Parameter:
7187: . mat - the matrix
7189: Output Parameters:
7190: + rbs - row block size
7191: - cbs - column block size
7193: Notes:
7194: Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7195: If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7197: If a block size has not been set yet this routine returns 1.
7199: Level: intermediate
7201: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7202: @*/
7203: PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7204: {
7208: if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7209: if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7210: return 0;
7211: }
7213: /*@
7214: MatSetBlockSize - Sets the matrix block size.
7216: Logically Collective on mat
7218: Input Parameters:
7219: + mat - the matrix
7220: - bs - block size
7222: Notes:
7223: Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7224: This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7226: For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7227: is compatible with the matrix local sizes.
7229: Level: intermediate
7231: .seealso: `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7232: @*/
7233: PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7234: {
7237: MatSetBlockSizes(mat, bs, bs);
7238: return 0;
7239: }
7241: typedef struct {
7242: PetscInt n;
7243: IS *is;
7244: Mat *mat;
7245: PetscObjectState nonzerostate;
7246: Mat C;
7247: } EnvelopeData;
7249: static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7250: {
7251: for (PetscInt i = 0; i < edata->n; i++) ISDestroy(&edata->is[i]);
7252: PetscFree(edata->is);
7253: PetscFree(edata);
7254: return 0;
7255: }
7257: /*
7258: MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7259: the sizes of these blocks in the matrix. An individual block may lie over several processes.
7261: Collective on mat
7263: Input Parameter:
7264: . mat - the matrix
7266: Notes:
7267: There can be zeros within the blocks
7269: The blocks can overlap between processes, including laying on more than two processes
7271: .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7272: */
7273: static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7274: {
7275: PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7276: PetscInt *diag, *odiag, sc;
7277: VecScatter scatter;
7278: PetscScalar *seqv;
7279: const PetscScalar *parv;
7280: const PetscInt *ia, *ja;
7281: PetscBool set, flag, done;
7282: Mat AA = mat, A;
7283: MPI_Comm comm;
7284: PetscMPIInt rank, size, tag;
7285: MPI_Status status;
7286: PetscContainer container;
7287: EnvelopeData *edata;
7288: Vec seq, par;
7289: IS isglobal;
7292: MatIsSymmetricKnown(mat, &set, &flag);
7293: if (!set || !flag) {
7294: /* TOO: only needs nonzero structure of transpose */
7295: MatTranspose(mat, MAT_INITIAL_MATRIX, &AA);
7296: MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN);
7297: }
7298: MatAIJGetLocalMat(AA, &A);
7299: MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7302: MatGetLocalSize(mat, &n, NULL);
7303: PetscObjectGetNewTag((PetscObject)mat, &tag);
7304: PetscObjectGetComm((PetscObject)mat, &comm);
7305: MPI_Comm_size(comm, &size);
7306: MPI_Comm_rank(comm, &rank);
7308: PetscMalloc2(n, &sizes, n, &starts);
7310: if (rank > 0) {
7311: MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status);
7312: MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status);
7313: }
7314: MatGetOwnershipRange(mat, &rstart, NULL);
7315: for (i = 0; i < n; i++) {
7316: env = PetscMax(env, ja[ia[i + 1] - 1]);
7317: II = rstart + i;
7318: if (env == II) {
7319: starts[lblocks] = tbs;
7320: sizes[lblocks++] = 1 + II - tbs;
7321: tbs = 1 + II;
7322: }
7323: }
7324: if (rank < size - 1) {
7325: MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm);
7326: MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm);
7327: }
7329: MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7330: if (!set || !flag) MatDestroy(&AA);
7331: MatDestroy(&A);
7333: PetscNew(&edata);
7334: MatGetNonzeroState(mat, &edata->nonzerostate);
7335: edata->n = lblocks;
7336: /* create IS needed for extracting blocks from the original matrix */
7337: PetscMalloc1(lblocks, &edata->is);
7338: for (PetscInt i = 0; i < lblocks; i++) ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]);
7340: /* Create the resulting inverse matrix structure with preallocation information */
7341: MatCreate(PetscObjectComm((PetscObject)mat), &edata->C);
7342: MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
7343: MatSetBlockSizesFromMats(edata->C, mat, mat);
7344: MatSetType(edata->C, MATAIJ);
7346: /* Communicate the start and end of each row, from each block to the correct rank */
7347: /* TODO: Use PetscSF instead of VecScatter */
7348: for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7349: VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq);
7350: VecGetArrayWrite(seq, &seqv);
7351: for (PetscInt i = 0; i < lblocks; i++) {
7352: for (PetscInt j = 0; j < sizes[i]; j++) {
7353: seqv[cnt] = starts[i];
7354: seqv[cnt + 1] = starts[i] + sizes[i];
7355: cnt += 2;
7356: }
7357: }
7358: VecRestoreArrayWrite(seq, &seqv);
7359: MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
7360: sc -= cnt;
7361: VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par);
7362: ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal);
7363: VecScatterCreate(seq, NULL, par, isglobal, &scatter);
7364: ISDestroy(&isglobal);
7365: VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7366: VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7367: VecScatterDestroy(&scatter);
7368: VecDestroy(&seq);
7369: MatGetOwnershipRangeColumn(mat, &cstart, &cend);
7370: PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag);
7371: VecGetArrayRead(par, &parv);
7372: cnt = 0;
7373: MatGetSize(mat, NULL, &n);
7374: for (PetscInt i = 0; i < mat->rmap->n; i++) {
7375: PetscInt start, end, d = 0, od = 0;
7377: start = (PetscInt)PetscRealPart(parv[cnt]);
7378: end = (PetscInt)PetscRealPart(parv[cnt + 1]);
7379: cnt += 2;
7381: if (start < cstart) {
7382: od += cstart - start + n - cend;
7383: d += cend - cstart;
7384: } else if (start < cend) {
7385: od += n - cend;
7386: d += cend - start;
7387: } else od += n - start;
7388: if (end <= cstart) {
7389: od -= cstart - end + n - cend;
7390: d -= cend - cstart;
7391: } else if (end < cend) {
7392: od -= n - cend;
7393: d -= cend - end;
7394: } else od -= n - end;
7396: odiag[i] = od;
7397: diag[i] = d;
7398: }
7399: VecRestoreArrayRead(par, &parv);
7400: VecDestroy(&par);
7401: MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL);
7402: PetscFree2(diag, odiag);
7403: PetscFree2(sizes, starts);
7405: PetscContainerCreate(PETSC_COMM_SELF, &container);
7406: PetscContainerSetPointer(container, edata);
7407: PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy);
7408: PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container);
7409: PetscObjectDereference((PetscObject)container);
7410: return 0;
7411: }
7413: /*@
7414: MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7416: Collective on A
7418: Input Parameters:
7419: . A - the matrix
7421: Output Parameters:
7422: . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set.
7424: Note:
7425: For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7427: Level: advanced
7429: .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7430: @*/
7431: PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7432: {
7433: PetscContainer container;
7434: EnvelopeData *edata;
7435: PetscObjectState nonzerostate;
7437: PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7438: if (!container) {
7439: MatComputeVariableBlockEnvelope(A);
7440: PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7441: }
7442: PetscContainerGetPointer(container, (void **)&edata);
7443: MatGetNonzeroState(A, &nonzerostate);
7447: MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat);
7448: *C = edata->C;
7450: for (PetscInt i = 0; i < edata->n; i++) {
7451: Mat D;
7452: PetscScalar *dvalues;
7454: MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D);
7455: MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE);
7456: MatSeqDenseInvert(D);
7457: MatDenseGetArray(D, &dvalues);
7458: MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES);
7459: MatDestroy(&D);
7460: }
7461: MatDestroySubMatrices(edata->n, &edata->mat);
7462: MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY);
7463: MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY);
7464: return 0;
7465: }
7467: /*@
7468: MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7470: Logically Collective on mat
7472: Input Parameters:
7473: + mat - the matrix
7474: . nblocks - the number of blocks on this process, each block can only exist on a single process
7475: - bsizes - the block sizes
7477: Notes:
7478: Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7480: Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks.
7482: Level: intermediate
7484: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7485: `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7486: @*/
7487: PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7488: {
7489: PetscInt i, ncnt = 0, nlocal;
7493: MatGetLocalSize(mat, &nlocal, NULL);
7494: for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7496: PetscFree(mat->bsizes);
7497: mat->nblocks = nblocks;
7498: PetscMalloc1(nblocks, &mat->bsizes);
7499: PetscArraycpy(mat->bsizes, bsizes, nblocks);
7500: return 0;
7501: }
7503: /*@C
7504: MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7506: Logically Collective on mat
7508: Input Parameter:
7509: . mat - the matrix
7511: Output Parameters:
7512: + nblocks - the number of blocks on this process
7513: - bsizes - the block sizes
7515: Fortran Note:
7516: Currently not supported from Fortran
7518: Level: intermediate
7520: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7521: @*/
7522: PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7523: {
7525: *nblocks = mat->nblocks;
7526: *bsizes = mat->bsizes;
7527: return 0;
7528: }
7530: /*@
7531: MatSetBlockSizes - Sets the matrix block row and column sizes.
7533: Logically Collective on mat
7535: Input Parameters:
7536: + mat - the matrix
7537: . rbs - row block size
7538: - cbs - column block size
7540: Notes:
7541: Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7542: If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7543: This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7545: For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7546: are compatible with the matrix local sizes.
7548: The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7550: Level: intermediate
7552: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7553: @*/
7554: PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7555: {
7559: PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7560: if (mat->rmap->refcnt) {
7561: ISLocalToGlobalMapping l2g = NULL;
7562: PetscLayout nmap = NULL;
7564: PetscLayoutDuplicate(mat->rmap, &nmap);
7565: if (mat->rmap->mapping) ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g);
7566: PetscLayoutDestroy(&mat->rmap);
7567: mat->rmap = nmap;
7568: mat->rmap->mapping = l2g;
7569: }
7570: if (mat->cmap->refcnt) {
7571: ISLocalToGlobalMapping l2g = NULL;
7572: PetscLayout nmap = NULL;
7574: PetscLayoutDuplicate(mat->cmap, &nmap);
7575: if (mat->cmap->mapping) ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g);
7576: PetscLayoutDestroy(&mat->cmap);
7577: mat->cmap = nmap;
7578: mat->cmap->mapping = l2g;
7579: }
7580: PetscLayoutSetBlockSize(mat->rmap, rbs);
7581: PetscLayoutSetBlockSize(mat->cmap, cbs);
7582: return 0;
7583: }
7585: /*@
7586: MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7588: Logically Collective on mat
7590: Input Parameters:
7591: + mat - the matrix
7592: . fromRow - matrix from which to copy row block size
7593: - fromCol - matrix from which to copy column block size (can be same as fromRow)
7595: Level: developer
7597: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7598: @*/
7599: PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7600: {
7604: if (fromRow->rmap->bs > 0) PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs);
7605: if (fromCol->cmap->bs > 0) PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs);
7606: return 0;
7607: }
7609: /*@
7610: MatResidual - Default routine to calculate the residual r = b - Ax
7612: Collective on mat
7614: Input Parameters:
7615: + mat - the matrix
7616: . b - the right-hand-side
7617: - x - the approximate solution
7619: Output Parameter:
7620: . r - location to store the residual
7622: Level: developer
7624: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7625: @*/
7626: PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7627: {
7633: MatCheckPreallocated(mat, 1);
7634: PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0);
7635: if (!mat->ops->residual) {
7636: MatMult(mat, x, r);
7637: VecAYPX(r, -1.0, b);
7638: } else {
7639: PetscUseTypeMethod(mat, residual, b, x, r);
7640: }
7641: PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0);
7642: return 0;
7643: }
7645: /*@C
7646: MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7648: Collective on mat
7650: Input Parameters:
7651: + mat - the matrix
7652: . shift - 0 or 1 indicating we want the indices starting at 0 or 1
7653: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7654: - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the
7655: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7656: always used.
7658: Output Parameters:
7659: + n - number of local rows in the (possibly compressed) matrix, use NULL if not needed
7660: . 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
7661: . ja - the column indices, use NULL if not needed
7662: - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7663: are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7665: Level: developer
7667: Notes:
7668: You CANNOT change any of the ia[] or ja[] values.
7670: Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7672: Fortran Notes:
7673: In Fortran use
7674: $
7675: $ PetscInt ia(1), ja(1)
7676: $ PetscOffset iia, jja
7677: $ call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7678: $ ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7680: or
7681: $
7682: $ PetscInt, pointer :: ia(:),ja(:)
7683: $ call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7684: $ ! Access the ith and jth entries via ia(i) and ja(j)
7686: .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7687: @*/
7688: PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7689: {
7696: MatCheckPreallocated(mat, 1);
7697: if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7698: else {
7699: if (done) *done = PETSC_TRUE;
7700: PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0);
7701: PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7702: PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0);
7703: }
7704: return 0;
7705: }
7707: /*@C
7708: MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7710: Collective on mat
7712: Input Parameters:
7713: + mat - the matrix
7714: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7715: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7716: symmetrized
7717: . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7718: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7719: always used.
7720: . n - number of columns in the (possibly compressed) matrix
7721: . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7722: - ja - the row indices
7724: Output Parameters:
7725: . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7727: Level: developer
7729: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7730: @*/
7731: PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7732: {
7739: MatCheckPreallocated(mat, 1);
7740: if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7741: else {
7742: *done = PETSC_TRUE;
7743: PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7744: }
7745: return 0;
7746: }
7748: /*@C
7749: MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7751: Collective on mat
7753: Input Parameters:
7754: + mat - the matrix
7755: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7756: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7757: . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7758: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7759: always used.
7760: . n - size of (possibly compressed) matrix
7761: . ia - the row pointers
7762: - ja - the column indices
7764: Output Parameters:
7765: . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7767: Note:
7768: This routine zeros out n, ia, and ja. This is to prevent accidental
7769: us of the array after it has been restored. If you pass NULL, it will
7770: not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7772: Level: developer
7774: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7775: @*/
7776: PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7777: {
7783: MatCheckPreallocated(mat, 1);
7785: if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7786: else {
7787: if (done) *done = PETSC_TRUE;
7788: PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7789: if (n) *n = 0;
7790: if (ia) *ia = NULL;
7791: if (ja) *ja = NULL;
7792: }
7793: return 0;
7794: }
7796: /*@C
7797: MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
7799: Collective on Mat
7801: Input Parameters:
7802: + mat - the matrix
7803: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7804: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7805: - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7806: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7807: always used.
7809: Output Parameters:
7810: + n - size of (possibly compressed) matrix
7811: . ia - the column pointers
7812: . ja - the row indices
7813: - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7815: Level: developer
7817: .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7818: @*/
7819: PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7820: {
7826: MatCheckPreallocated(mat, 1);
7828: if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7829: else {
7830: *done = PETSC_TRUE;
7831: PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7832: if (n) *n = 0;
7833: if (ia) *ia = NULL;
7834: if (ja) *ja = NULL;
7835: }
7836: return 0;
7837: }
7839: /*@C
7840: MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
7842: Collective on mat
7844: Input Parameters:
7845: + mat - the matrix
7846: . ncolors - max color value
7847: . n - number of entries in colorarray
7848: - colorarray - array indicating color for each column
7850: Output Parameters:
7851: . iscoloring - coloring generated using colorarray information
7853: Level: developer
7855: .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7856: @*/
7857: PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
7858: {
7863: MatCheckPreallocated(mat, 1);
7865: if (!mat->ops->coloringpatch) {
7866: ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring);
7867: } else {
7868: PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7869: }
7870: return 0;
7871: }
7873: /*@
7874: MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
7876: Logically Collective on mat
7878: Input Parameter:
7879: . mat - the factored matrix to be reset
7881: Notes:
7882: This routine should be used only with factored matrices formed by in-place
7883: factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
7884: format). This option can save memory, for example, when solving nonlinear
7885: systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7886: ILU(0) preconditioner.
7888: Note that one can specify in-place ILU(0) factorization by calling
7889: .vb
7890: PCType(pc,PCILU);
7891: PCFactorSeUseInPlace(pc);
7892: .ve
7893: or by using the options -pc_type ilu -pc_factor_in_place
7895: In-place factorization ILU(0) can also be used as a local
7896: solver for the blocks within the block Jacobi or additive Schwarz
7897: methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc
7898: for details on setting local solver options.
7900: Most users should employ the `KSP` interface for linear solvers
7901: instead of working directly with matrix algebra routines such as this.
7902: See, e.g., `KSPCreate()`.
7904: Level: developer
7906: .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7907: @*/
7908: PetscErrorCode MatSetUnfactored(Mat mat)
7909: {
7912: MatCheckPreallocated(mat, 1);
7913: mat->factortype = MAT_FACTOR_NONE;
7914: if (!mat->ops->setunfactored) return 0;
7915: PetscUseTypeMethod(mat, setunfactored);
7916: return 0;
7917: }
7919: /*MC
7920: MatDenseGetArrayF90 - Accesses a matrix array from Fortran
7922: Synopsis:
7923: MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7925: Not collective
7927: Input Parameter:
7928: . x - matrix
7930: Output Parameters:
7931: + xx_v - the Fortran pointer to the array
7932: - ierr - error code
7934: Example of Usage:
7935: .vb
7936: PetscScalar, pointer xx_v(:,:)
7937: ....
7938: call MatDenseGetArrayF90(x,xx_v,ierr)
7939: a = xx_v(3)
7940: call MatDenseRestoreArrayF90(x,xx_v,ierr)
7941: .ve
7943: Level: advanced
7945: .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
7947: M*/
7949: /*MC
7950: MatDenseRestoreArrayF90 - Restores a matrix array that has been
7951: accessed with `MatDenseGetArrayF90()`.
7953: Synopsis:
7954: MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7956: Not collective
7958: Input Parameters:
7959: + x - matrix
7960: - xx_v - the Fortran90 pointer to the array
7962: Output Parameter:
7963: . ierr - error code
7965: Example of Usage:
7966: .vb
7967: PetscScalar, pointer xx_v(:,:)
7968: ....
7969: call MatDenseGetArrayF90(x,xx_v,ierr)
7970: a = xx_v(3)
7971: call MatDenseRestoreArrayF90(x,xx_v,ierr)
7972: .ve
7974: Level: advanced
7976: .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
7978: M*/
7980: /*MC
7981: MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
7983: Synopsis:
7984: MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7986: Not collective
7988: Input Parameter:
7989: . x - matrix
7991: Output Parameters:
7992: + xx_v - the Fortran pointer to the array
7993: - ierr - error code
7995: Example of Usage:
7996: .vb
7997: PetscScalar, pointer xx_v(:)
7998: ....
7999: call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8000: a = xx_v(3)
8001: call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8002: .ve
8004: Level: advanced
8006: .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8008: M*/
8010: /*MC
8011: MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8012: accessed with `MatSeqAIJGetArrayF90()`.
8014: Synopsis:
8015: MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8017: Not collective
8019: Input Parameters:
8020: + x - matrix
8021: - xx_v - the Fortran90 pointer to the array
8023: Output Parameter:
8024: . ierr - error code
8026: Example of Usage:
8027: .vb
8028: PetscScalar, pointer xx_v(:)
8029: ....
8030: call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8031: a = xx_v(3)
8032: call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8033: .ve
8035: Level: advanced
8037: .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8039: M*/
8041: /*@
8042: MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8043: as the original matrix.
8045: Collective on mat
8047: Input Parameters:
8048: + mat - the original matrix
8049: . isrow - parallel IS containing the rows this processor should obtain
8050: . 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.
8051: - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8053: Output Parameter:
8054: . newmat - the new submatrix, of the same type as the old
8056: Level: advanced
8058: Notes:
8059: The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8061: Some matrix types place restrictions on the row and column indices, such
8062: as that they be sorted or that they be equal to each other.
8064: The index sets may not have duplicate entries.
8066: The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8067: the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8068: to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8069: will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when
8070: you are finished using it.
8072: The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8073: the input matrix.
8075: If iscol is NULL then all columns are obtained (not supported in Fortran).
8077: Example usage:
8078: Consider the following 8x8 matrix with 34 non-zero values, that is
8079: assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8080: proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8081: as follows:
8083: .vb
8084: 1 2 0 | 0 3 0 | 0 4
8085: Proc0 0 5 6 | 7 0 0 | 8 0
8086: 9 0 10 | 11 0 0 | 12 0
8087: -------------------------------------
8088: 13 0 14 | 15 16 17 | 0 0
8089: Proc1 0 18 0 | 19 20 21 | 0 0
8090: 0 0 0 | 22 23 0 | 24 0
8091: -------------------------------------
8092: Proc2 25 26 27 | 0 0 28 | 29 0
8093: 30 0 0 | 31 32 33 | 0 34
8094: .ve
8096: Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is
8098: .vb
8099: 2 0 | 0 3 0 | 0
8100: Proc0 5 6 | 7 0 0 | 8
8101: -------------------------------
8102: Proc1 18 0 | 19 20 21 | 0
8103: -------------------------------
8104: Proc2 26 27 | 0 0 28 | 29
8105: 0 0 | 31 32 33 | 0
8106: .ve
8108: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8109: @*/
8110: PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8111: {
8112: PetscMPIInt size;
8113: Mat *local;
8114: IS iscoltmp;
8115: PetscBool flg;
8126: MatCheckPreallocated(mat, 1);
8127: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8129: if (!iscol || isrow == iscol) {
8130: PetscBool stride;
8131: PetscMPIInt grabentirematrix = 0, grab;
8132: PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride);
8133: if (stride) {
8134: PetscInt first, step, n, rstart, rend;
8135: ISStrideGetInfo(isrow, &first, &step);
8136: if (step == 1) {
8137: MatGetOwnershipRange(mat, &rstart, &rend);
8138: if (rstart == first) {
8139: ISGetLocalSize(isrow, &n);
8140: if (n == rend - rstart) grabentirematrix = 1;
8141: }
8142: }
8143: }
8144: MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat));
8145: if (grab) {
8146: PetscInfo(mat, "Getting entire matrix as submatrix\n");
8147: if (cll == MAT_INITIAL_MATRIX) {
8148: *newmat = mat;
8149: PetscObjectReference((PetscObject)mat);
8150: }
8151: return 0;
8152: }
8153: }
8155: if (!iscol) {
8156: ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp);
8157: } else {
8158: iscoltmp = iscol;
8159: }
8161: /* if original matrix is on just one processor then use submatrix generated */
8162: if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8163: MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat);
8164: goto setproperties;
8165: } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8166: MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local);
8167: *newmat = *local;
8168: PetscFree(local);
8169: goto setproperties;
8170: } else if (!mat->ops->createsubmatrix) {
8171: /* Create a new matrix type that implements the operation using the full matrix */
8172: PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8173: switch (cll) {
8174: case MAT_INITIAL_MATRIX:
8175: MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat);
8176: break;
8177: case MAT_REUSE_MATRIX:
8178: MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp);
8179: break;
8180: default:
8181: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8182: }
8183: PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8184: goto setproperties;
8185: }
8187: PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8188: PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8189: PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8191: setproperties:
8192: ISEqualUnsorted(isrow, iscoltmp, &flg);
8193: if (flg) MatPropagateSymmetryOptions(mat, *newmat);
8194: if (!iscol) ISDestroy(&iscoltmp);
8195: if (*newmat && cll == MAT_INITIAL_MATRIX) PetscObjectStateIncrease((PetscObject)*newmat);
8196: return 0;
8197: }
8199: /*@
8200: MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8202: Not Collective
8204: Input Parameters:
8205: + A - the matrix we wish to propagate options from
8206: - B - the matrix we wish to propagate options to
8208: Level: beginner
8210: Note:
8211: Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8213: .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8214: @*/
8215: PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8216: {
8219: B->symmetry_eternal = A->symmetry_eternal;
8220: B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8221: B->symmetric = A->symmetric;
8222: B->structurally_symmetric = A->structurally_symmetric;
8223: B->spd = A->spd;
8224: B->hermitian = A->hermitian;
8225: return 0;
8226: }
8228: /*@
8229: MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8230: used during the assembly process to store values that belong to
8231: other processors.
8233: Not Collective
8235: Input Parameters:
8236: + mat - the matrix
8237: . size - the initial size of the stash.
8238: - bsize - the initial size of the block-stash(if used).
8240: Options Database Keys:
8241: + -matstash_initial_size <size> or <size0,size1,...sizep-1>
8242: - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1>
8244: Level: intermediate
8246: Notes:
8247: The block-stash is used for values set with `MatSetValuesBlocked()` while
8248: the stash is used for values set with `MatSetValues()`
8250: Run with the option -info and look for output of the form
8251: MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8252: to determine the appropriate value, MM, to use for size and
8253: MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8254: to determine the value, BMM to use for bsize
8256: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8257: @*/
8258: PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8259: {
8262: MatStashSetInitialSize_Private(&mat->stash, size);
8263: MatStashSetInitialSize_Private(&mat->bstash, bsize);
8264: return 0;
8265: }
8267: /*@
8268: MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8269: the matrix
8271: Neighbor-wise Collective on mat
8273: Input Parameters:
8274: + mat - the matrix
8275: . x,y - the vectors
8276: - w - where the result is stored
8278: Level: intermediate
8280: Notes:
8281: w may be the same vector as y.
8283: This allows one to use either the restriction or interpolation (its transpose)
8284: matrix to do the interpolation
8286: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8287: @*/
8288: PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8289: {
8290: PetscInt M, N, Ny;
8296: MatGetSize(A, &M, &N);
8297: VecGetSize(y, &Ny);
8298: if (M == Ny) {
8299: MatMultAdd(A, x, y, w);
8300: } else {
8301: MatMultTransposeAdd(A, x, y, w);
8302: }
8303: return 0;
8304: }
8306: /*@
8307: MatInterpolate - y = A*x or A'*x depending on the shape of
8308: the matrix
8310: Neighbor-wise Collective on mat
8312: Input Parameters:
8313: + mat - the matrix
8314: - x,y - the vectors
8316: Level: intermediate
8318: Note:
8319: This allows one to use either the restriction or interpolation (its transpose)
8320: matrix to do the interpolation
8322: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8323: @*/
8324: PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8325: {
8326: PetscInt M, N, Ny;
8331: MatGetSize(A, &M, &N);
8332: VecGetSize(y, &Ny);
8333: if (M == Ny) {
8334: MatMult(A, x, y);
8335: } else {
8336: MatMultTranspose(A, x, y);
8337: }
8338: return 0;
8339: }
8341: /*@
8342: MatRestrict - y = A*x or A'*x
8344: Neighbor-wise Collective on Mat
8346: Input Parameters:
8347: + mat - the matrix
8348: - x,y - the vectors
8350: Level: intermediate
8352: Note:
8353: This allows one to use either the restriction or interpolation (its transpose)
8354: matrix to do the restriction
8356: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8357: @*/
8358: PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8359: {
8360: PetscInt M, N, Ny;
8365: MatGetSize(A, &M, &N);
8366: VecGetSize(y, &Ny);
8367: if (M == Ny) {
8368: MatMult(A, x, y);
8369: } else {
8370: MatMultTranspose(A, x, y);
8371: }
8372: return 0;
8373: }
8375: /*@
8376: MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8378: Neighbor-wise Collective on Mat
8380: Input Parameters:
8381: + mat - the matrix
8382: - w, x - the input dense matrices
8384: Output Parameters:
8385: . y - the output dense matrix
8387: Level: intermediate
8389: Note:
8390: This allows one to use either the restriction or interpolation (its transpose)
8391: matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8392: otherwise it will be recreated. y must be initialized to NULL if not supplied.
8394: .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8395: @*/
8396: PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8397: {
8398: PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8399: PetscBool trans = PETSC_TRUE;
8400: MatReuse reuse = MAT_INITIAL_MATRIX;
8407: MatGetSize(A, &M, &N);
8408: MatGetSize(x, &Mx, &Nx);
8409: if (N == Mx) trans = PETSC_FALSE;
8411: Mo = trans ? N : M;
8412: if (*y) {
8413: MatGetSize(*y, &My, &Ny);
8414: if (Mo == My && Nx == Ny) {
8415: reuse = MAT_REUSE_MATRIX;
8416: } else {
8418: MatDestroy(y);
8419: }
8420: }
8422: if (w && *y == w) { /* this is to minimize changes in PCMG */
8423: PetscBool flg;
8425: PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w);
8426: if (w) {
8427: PetscInt My, Ny, Mw, Nw;
8429: PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg);
8430: MatGetSize(*y, &My, &Ny);
8431: MatGetSize(w, &Mw, &Nw);
8432: if (!flg || My != Mw || Ny != Nw) w = NULL;
8433: }
8434: if (!w) {
8435: MatDuplicate(*y, MAT_COPY_VALUES, &w);
8436: PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w);
8437: PetscObjectDereference((PetscObject)w);
8438: } else {
8439: MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN);
8440: }
8441: }
8442: if (!trans) {
8443: MatMatMult(A, x, reuse, PETSC_DEFAULT, y);
8444: } else {
8445: MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y);
8446: }
8447: if (w) MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN);
8448: return 0;
8449: }
8451: /*@
8452: MatMatInterpolate - Y = A*X or A'*X
8454: Neighbor-wise Collective on Mat
8456: Input Parameters:
8457: + mat - the matrix
8458: - x - the input dense matrix
8460: Output Parameters:
8461: . y - the output dense matrix
8463: Level: intermediate
8465: Note:
8466: This allows one to use either the restriction or interpolation (its transpose)
8467: matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8468: otherwise it will be recreated. y must be initialized to NULL if not supplied.
8470: .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8471: @*/
8472: PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8473: {
8474: MatMatInterpolateAdd(A, x, NULL, y);
8475: return 0;
8476: }
8478: /*@
8479: MatMatRestrict - Y = A*X or A'*X
8481: Neighbor-wise Collective on Mat
8483: Input Parameters:
8484: + mat - the matrix
8485: - x - the input dense matrix
8487: Output Parameters:
8488: . y - the output dense matrix
8490: Level: intermediate
8492: Note:
8493: This allows one to use either the restriction or interpolation (its transpose)
8494: matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8495: otherwise it will be recreated. y must be initialized to NULL if not supplied.
8497: .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8498: @*/
8499: PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8500: {
8501: MatMatInterpolateAdd(A, x, NULL, y);
8502: return 0;
8503: }
8505: /*@
8506: MatGetNullSpace - retrieves the null space of a matrix.
8508: Logically Collective on mat
8510: Input Parameters:
8511: + mat - the matrix
8512: - nullsp - the null space object
8514: Level: developer
8516: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8517: @*/
8518: PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8519: {
8522: *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8523: return 0;
8524: }
8526: /*@
8527: MatSetNullSpace - attaches a null space to a matrix.
8529: Logically Collective on mat
8531: Input Parameters:
8532: + mat - the matrix
8533: - nullsp - the null space object
8535: Level: advanced
8537: Notes:
8538: This null space is used by the `KSP` linear solvers to solve singular systems.
8540: 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
8542: 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 to
8543: to zero but the linear system will still be solved in a least squares sense.
8545: The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8546: 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), + the range of A^T, R(A^T).
8547: 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
8548: 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
8549: 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).
8550: This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8552: If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8553: `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8554: routine also automatically calls `MatSetTransposeNullSpace()`.
8556: The user should call `MatNullSpaceDestroy()`.
8558: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8559: `KSPSetPCSide()`
8560: @*/
8561: PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8562: {
8565: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8566: MatNullSpaceDestroy(&mat->nullsp);
8567: mat->nullsp = nullsp;
8568: if (mat->symmetric == PETSC_BOOL3_TRUE) MatSetTransposeNullSpace(mat, nullsp);
8569: return 0;
8570: }
8572: /*@
8573: MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8575: Logically Collective on mat
8577: Input Parameters:
8578: + mat - the matrix
8579: - nullsp - the null space object
8581: Level: developer
8583: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8584: @*/
8585: PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8586: {
8590: *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8591: return 0;
8592: }
8594: /*@
8595: MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8597: Logically Collective on mat
8599: Input Parameters:
8600: + mat - the matrix
8601: - nullsp - the null space object
8603: Level: advanced
8605: Notes:
8606: This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8608: See `MatSetNullSpace()`
8610: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8611: @*/
8612: PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8613: {
8616: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8617: MatNullSpaceDestroy(&mat->transnullsp);
8618: mat->transnullsp = nullsp;
8619: return 0;
8620: }
8622: /*@
8623: MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8624: This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8626: Logically Collective on mat
8628: Input Parameters:
8629: + mat - the matrix
8630: - nullsp - the null space object
8632: Level: advanced
8634: Notes:
8635: Overwrites any previous near null space that may have been attached
8637: You can remove the null space by calling this routine with an nullsp of NULL
8639: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8640: @*/
8641: PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8642: {
8646: MatCheckPreallocated(mat, 1);
8647: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8648: MatNullSpaceDestroy(&mat->nearnullsp);
8649: mat->nearnullsp = nullsp;
8650: return 0;
8651: }
8653: /*@
8654: MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8656: Not Collective
8658: Input Parameter:
8659: . mat - the matrix
8661: Output Parameter:
8662: . nullsp - the null space object, NULL if not set
8664: Level: advanced
8666: .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8667: @*/
8668: PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8669: {
8673: MatCheckPreallocated(mat, 1);
8674: *nullsp = mat->nearnullsp;
8675: return 0;
8676: }
8678: /*@C
8679: MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8681: Collective on mat
8683: Input Parameters:
8684: + mat - the matrix
8685: . row - row/column permutation
8686: . fill - expected fill factor >= 1.0
8687: - level - level of fill, for ICC(k)
8689: Notes:
8690: Probably really in-place only when level of fill is zero, otherwise allocates
8691: new space to store factored matrix and deletes previous memory.
8693: Most users should employ the `KSP` interface for linear solvers
8694: instead of working directly with matrix algebra routines such as this.
8695: See, e.g., `KSPCreate()`.
8697: Level: developer
8699: Developer Note:
8700: The Fortran interface is not autogenerated as the f90
8701: interface definition cannot be generated correctly [due to `MatFactorInfo`]
8703: .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8704: @*/
8705: PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8706: {
8714: MatCheckPreallocated(mat, 1);
8715: PetscUseTypeMethod(mat, iccfactor, row, info);
8716: PetscObjectStateIncrease((PetscObject)mat);
8717: return 0;
8718: }
8720: /*@
8721: MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8722: ghosted ones.
8724: Not Collective
8726: Input Parameters:
8727: + mat - the matrix
8728: - diag - the diagonal values, including ghost ones
8730: Level: developer
8732: Notes:
8733: Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8735: This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8737: .seealso: `MatDiagonalScale()`
8738: @*/
8739: PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8740: {
8741: PetscMPIInt size;
8748: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
8749: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8750: if (size == 1) {
8751: PetscInt n, m;
8752: VecGetSize(diag, &n);
8753: MatGetSize(mat, NULL, &m);
8754: if (m == n) {
8755: MatDiagonalScale(mat, NULL, diag);
8756: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8757: } else {
8758: PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8759: }
8760: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
8761: PetscObjectStateIncrease((PetscObject)mat);
8762: return 0;
8763: }
8765: /*@
8766: MatGetInertia - Gets the inertia from a factored matrix
8768: Collective on mat
8770: Input Parameter:
8771: . mat - the matrix
8773: Output Parameters:
8774: + nneg - number of negative eigenvalues
8775: . nzero - number of zero eigenvalues
8776: - npos - number of positive eigenvalues
8778: Level: advanced
8780: Note:
8781: Matrix must have been factored by `MatCholeskyFactor()`
8783: .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8784: @*/
8785: PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8786: {
8791: PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8792: return 0;
8793: }
8795: /* ----------------------------------------------------------------*/
8796: /*@C
8797: MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8799: Neighbor-wise Collective on mat
8801: Input Parameters:
8802: + mat - the factored matrix obtained with `MatGetFactor()`
8803: - b - the right-hand-side vectors
8805: Output Parameter:
8806: . x - the result vectors
8808: Note:
8809: The vectors b and x cannot be the same. I.e., one cannot
8810: call `MatSolves`(A,x,x).
8812: Level: developer
8814: .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8815: @*/
8816: PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
8817: {
8822: if (!mat->rmap->N && !mat->cmap->N) return 0;
8824: MatCheckPreallocated(mat, 1);
8825: PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0);
8826: PetscUseTypeMethod(mat, solves, b, x);
8827: PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0);
8828: return 0;
8829: }
8831: /*@
8832: MatIsSymmetric - Test whether a matrix is symmetric
8834: Collective on mat
8836: Input Parameters:
8837: + A - the matrix to test
8838: - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
8840: Output Parameters:
8841: . flg - the result
8843: Notes:
8844: For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8846: If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
8848: One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8849: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8851: Level: intermediate
8853: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
8854: `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8855: @*/
8856: PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
8857: {
8861: if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8862: else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8863: else {
8864: if (!A->ops->issymmetric) {
8865: MatType mattype;
8866: MatGetType(A, &mattype);
8867: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8868: }
8869: PetscUseTypeMethod(A, issymmetric, tol, flg);
8870: if (!tol) MatSetOption(A, MAT_SYMMETRIC, *flg);
8871: }
8872: return 0;
8873: }
8875: /*@
8876: MatIsHermitian - Test whether a matrix is Hermitian
8878: Collective on Mat
8880: Input Parameters:
8881: + A - the matrix to test
8882: - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
8884: Output Parameters:
8885: . flg - the result
8887: Level: intermediate
8889: Notes:
8890: For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8892: If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
8894: One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8895: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
8897: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8898: `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8899: @*/
8900: PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
8901: {
8905: if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8906: else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8907: else {
8908: if (!A->ops->ishermitian) {
8909: MatType mattype;
8910: MatGetType(A, &mattype);
8911: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8912: }
8913: PetscUseTypeMethod(A, ishermitian, tol, flg);
8914: if (!tol) MatSetOption(A, MAT_HERMITIAN, *flg);
8915: }
8916: return 0;
8917: }
8919: /*@
8920: MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
8922: Not Collective
8924: Input Parameter:
8925: . A - the matrix to check
8927: Output Parameters:
8928: + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
8929: - flg - the result (only valid if set is `PETSC_TRUE`)
8931: Level: advanced
8933: Notes:
8934: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
8935: if you want it explicitly checked
8937: One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8938: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8940: .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8941: @*/
8942: PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
8943: {
8947: if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8948: *set = PETSC_TRUE;
8949: *flg = PetscBool3ToBool(A->symmetric);
8950: } else {
8951: *set = PETSC_FALSE;
8952: }
8953: return 0;
8954: }
8956: /*@
8957: MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
8959: Not Collective
8961: Input Parameter:
8962: . A - the matrix to check
8964: Output Parameters:
8965: + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
8966: - flg - the result (only valid if set is `PETSC_TRUE`)
8968: Level: advanced
8970: Notes:
8971: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
8973: One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
8974: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
8976: .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8977: @*/
8978: PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
8979: {
8983: if (A->spd != PETSC_BOOL3_UNKNOWN) {
8984: *set = PETSC_TRUE;
8985: *flg = PetscBool3ToBool(A->spd);
8986: } else {
8987: *set = PETSC_FALSE;
8988: }
8989: return 0;
8990: }
8992: /*@
8993: MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
8995: Not Collective
8997: Input Parameter:
8998: . A - the matrix to check
9000: Output Parameters:
9001: + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9002: - flg - the result (only valid if set is `PETSC_TRUE`)
9004: Level: advanced
9006: Notes:
9007: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9008: if you want it explicitly checked
9010: One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9011: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9013: .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9014: @*/
9015: PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9016: {
9020: if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9021: *set = PETSC_TRUE;
9022: *flg = PetscBool3ToBool(A->hermitian);
9023: } else {
9024: *set = PETSC_FALSE;
9025: }
9026: return 0;
9027: }
9029: /*@
9030: MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9032: Collective on Mat
9034: Input Parameter:
9035: . A - the matrix to test
9037: Output Parameters:
9038: . flg - the result
9040: Notes:
9041: If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9043: 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
9044: symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9046: Level: intermediate
9048: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9049: @*/
9050: PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9051: {
9054: if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9055: *flg = PetscBool3ToBool(A->structurally_symmetric);
9056: } else {
9057: PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9058: MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg);
9059: }
9060: return 0;
9061: }
9063: /*@
9064: MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9066: Not Collective
9068: Input Parameter:
9069: . A - the matrix to check
9071: Output Parameters:
9072: + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9073: - flg - the result (only valid if set is PETSC_TRUE)
9075: Level: advanced
9077: Notes:
9078: 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
9079: symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9081: Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9083: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9084: @*/
9085: PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9086: {
9090: if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9091: *set = PETSC_TRUE;
9092: *flg = PetscBool3ToBool(A->structurally_symmetric);
9093: } else {
9094: *set = PETSC_FALSE;
9095: }
9096: return 0;
9097: }
9099: /*@
9100: MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9101: to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9103: Not collective
9105: Input Parameter:
9106: . mat - the matrix
9108: Output Parameters:
9109: + nstash - the size of the stash
9110: . reallocs - the number of additional mallocs incurred.
9111: . bnstash - the size of the block stash
9112: - breallocs - the number of additional mallocs incurred.in the block stash
9114: Level: advanced
9116: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9117: @*/
9118: PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9119: {
9120: MatStashGetInfo_Private(&mat->stash, nstash, reallocs);
9121: MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs);
9122: return 0;
9123: }
9125: /*@C
9126: MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9127: parallel layout, `PetscLayout` for rows and columns
9129: Collective on mat
9131: Input Parameter:
9132: . mat - the matrix
9134: Output Parameters:
9135: + right - (optional) vector that the matrix can be multiplied against
9136: - left - (optional) vector that the matrix vector product can be stored in
9138: Notes:
9139: 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()`.
9141: These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9143: Level: advanced
9145: .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9146: @*/
9147: PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9148: {
9151: if (mat->ops->getvecs) {
9152: PetscUseTypeMethod(mat, getvecs, right, left);
9153: } else {
9154: PetscInt rbs, cbs;
9155: MatGetBlockSizes(mat, &rbs, &cbs);
9156: if (right) {
9158: VecCreate(PetscObjectComm((PetscObject)mat), right);
9159: VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE);
9160: VecSetBlockSize(*right, cbs);
9161: VecSetType(*right, mat->defaultvectype);
9162: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9163: if (mat->boundtocpu && mat->bindingpropagates) {
9164: VecSetBindingPropagates(*right, PETSC_TRUE);
9165: VecBindToCPU(*right, PETSC_TRUE);
9166: }
9167: #endif
9168: PetscLayoutReference(mat->cmap, &(*right)->map);
9169: }
9170: if (left) {
9172: VecCreate(PetscObjectComm((PetscObject)mat), left);
9173: VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE);
9174: VecSetBlockSize(*left, rbs);
9175: VecSetType(*left, mat->defaultvectype);
9176: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9177: if (mat->boundtocpu && mat->bindingpropagates) {
9178: VecSetBindingPropagates(*left, PETSC_TRUE);
9179: VecBindToCPU(*left, PETSC_TRUE);
9180: }
9181: #endif
9182: PetscLayoutReference(mat->rmap, &(*left)->map);
9183: }
9184: }
9185: return 0;
9186: }
9188: /*@C
9189: MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9190: with default values.
9192: Not Collective
9194: Input Parameters:
9195: . info - the `MatFactorInfo` data structure
9197: Notes:
9198: The solvers are generally used through the `KSP` and `PC` objects, for example
9199: `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9201: Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9203: Level: developer
9205: Developer Note:
9206: The Fortran interface is not autogenerated as the f90
9207: interface definition cannot be generated correctly [due to `MatFactorInfo`]
9209: .seealso: `MatGetFactor()`, `MatFactorInfo`
9210: @*/
9211: PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9212: {
9213: PetscMemzero(info, sizeof(MatFactorInfo));
9214: return 0;
9215: }
9217: /*@
9218: MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9220: Collective on mat
9222: Input Parameters:
9223: + mat - the factored matrix
9224: - is - the index set defining the Schur indices (0-based)
9226: Notes:
9227: Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9229: You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9231: This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9233: Level: advanced
9235: .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9236: `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9238: @*/
9239: PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9240: {
9241: PetscErrorCode (*f)(Mat, IS);
9249: PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f);
9251: MatDestroy(&mat->schur);
9252: (*f)(mat, is);
9254: return 0;
9255: }
9257: /*@
9258: MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9260: Logically Collective on mat
9262: Input Parameters:
9263: + F - the factored matrix obtained by calling `MatGetFactor()`
9264: . S - location where to return the Schur complement, can be NULL
9265: - status - the status of the Schur complement matrix, can be NULL
9267: Notes:
9268: You must call `MatFactorSetSchurIS()` before calling this routine.
9270: This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9272: The routine provides a copy of the Schur matrix stored within the solver data structures.
9273: The caller must destroy the object when it is no longer needed.
9274: If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9276: 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)
9278: See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9280: Developer Note:
9281: The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9282: matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9284: Level: advanced
9286: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9287: @*/
9288: PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9289: {
9293: if (S) {
9294: PetscErrorCode (*f)(Mat, Mat *);
9296: PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f);
9297: if (f) {
9298: (*f)(F, S);
9299: } else {
9300: MatDuplicate(F->schur, MAT_COPY_VALUES, S);
9301: }
9302: }
9303: if (status) *status = F->schur_status;
9304: return 0;
9305: }
9307: /*@
9308: MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9310: Logically Collective on mat
9312: Input Parameters:
9313: + F - the factored matrix obtained by calling `MatGetFactor()`
9314: . *S - location where to return the Schur complement, can be NULL
9315: - status - the status of the Schur complement matrix, can be NULL
9317: Notes:
9318: You must call `MatFactorSetSchurIS()` before calling this routine.
9320: Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9322: The routine returns a the Schur Complement stored within the data strutures of the solver.
9324: If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9326: The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9328: Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9330: See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9332: Level: advanced
9334: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9335: @*/
9336: PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9337: {
9341: if (S) *S = F->schur;
9342: if (status) *status = F->schur_status;
9343: return 0;
9344: }
9346: /*@
9347: MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9349: Logically Collective on mat
9351: Input Parameters:
9352: + F - the factored matrix obtained by calling `MatGetFactor()`
9353: . *S - location where the Schur complement is stored
9354: - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9356: Level: advanced
9358: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9359: @*/
9360: PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9361: {
9363: if (S) {
9365: *S = NULL;
9366: }
9367: F->schur_status = status;
9368: MatFactorUpdateSchurStatus_Private(F);
9369: return 0;
9370: }
9372: /*@
9373: MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9375: Logically Collective on mat
9377: Input Parameters:
9378: + F - the factored matrix obtained by calling `MatGetFactor()`
9379: . rhs - location where the right hand side of the Schur complement system is stored
9380: - sol - location where the solution of the Schur complement system has to be returned
9382: Notes:
9383: The sizes of the vectors should match the size of the Schur complement
9385: Must be called after `MatFactorSetSchurIS()`
9387: Level: advanced
9389: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9390: @*/
9391: PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9392: {
9401: MatFactorFactorizeSchurComplement(F);
9402: switch (F->schur_status) {
9403: case MAT_FACTOR_SCHUR_FACTORED:
9404: MatSolveTranspose(F->schur, rhs, sol);
9405: break;
9406: case MAT_FACTOR_SCHUR_INVERTED:
9407: MatMultTranspose(F->schur, rhs, sol);
9408: break;
9409: default:
9410: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9411: }
9412: return 0;
9413: }
9415: /*@
9416: MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9418: Logically Collective on mat
9420: Input Parameters:
9421: + F - the factored matrix obtained by calling `MatGetFactor()`
9422: . rhs - location where the right hand side of the Schur complement system is stored
9423: - sol - location where the solution of the Schur complement system has to be returned
9425: Notes:
9426: The sizes of the vectors should match the size of the Schur complement
9428: Must be called after `MatFactorSetSchurIS()`
9430: Level: advanced
9432: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9433: @*/
9434: PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9435: {
9444: MatFactorFactorizeSchurComplement(F);
9445: switch (F->schur_status) {
9446: case MAT_FACTOR_SCHUR_FACTORED:
9447: MatSolve(F->schur, rhs, sol);
9448: break;
9449: case MAT_FACTOR_SCHUR_INVERTED:
9450: MatMult(F->schur, rhs, sol);
9451: break;
9452: default:
9453: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9454: }
9455: return 0;
9456: }
9458: /*@
9459: MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9461: Logically Collective on F
9463: Input Parameters:
9464: . F - the factored matrix obtained by calling `MatGetFactor()`
9466: Notes:
9467: Must be called after `MatFactorSetSchurIS()`.
9469: Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9471: Level: advanced
9473: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9474: @*/
9475: PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9476: {
9479: if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) return 0;
9480: MatFactorFactorizeSchurComplement(F);
9481: MatFactorInvertSchurComplement_Private(F);
9482: F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9483: return 0;
9484: }
9486: /*@
9487: MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9489: Logically Collective on mat
9491: Input Parameters:
9492: . F - the factored matrix obtained by calling `MatGetFactor()`
9494: Note:
9495: Must be called after `MatFactorSetSchurIS()`
9497: Level: advanced
9499: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9500: @*/
9501: PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9502: {
9505: if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) return 0;
9506: MatFactorFactorizeSchurComplement_Private(F);
9507: F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9508: return 0;
9509: }
9511: /*@
9512: MatPtAP - Creates the matrix product C = P^T * A * P
9514: Neighbor-wise Collective on A
9516: Input Parameters:
9517: + A - the matrix
9518: . P - the projection matrix
9519: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9520: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9521: if the result is a dense matrix this is irrelevant
9523: Output Parameters:
9524: . C - the product matrix
9526: Notes:
9527: C will be created and must be destroyed by the user with `MatDestroy()`.
9529: An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9531: Developer Note:
9532: For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9534: Level: intermediate
9536: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9537: @*/
9538: PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9539: {
9540: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9543: if (scall == MAT_INITIAL_MATRIX) {
9544: MatProductCreate(A, P, NULL, C);
9545: MatProductSetType(*C, MATPRODUCT_PtAP);
9546: MatProductSetAlgorithm(*C, "default");
9547: MatProductSetFill(*C, fill);
9549: (*C)->product->api_user = PETSC_TRUE;
9550: MatProductSetFromOptions(*C);
9552: MatProductSymbolic(*C);
9553: } else { /* scall == MAT_REUSE_MATRIX */
9554: MatProductReplaceMats(A, P, NULL, *C);
9555: }
9557: MatProductNumeric(*C);
9558: (*C)->symmetric = A->symmetric;
9559: (*C)->spd = A->spd;
9560: return 0;
9561: }
9563: /*@
9564: MatRARt - Creates the matrix product C = R * A * R^T
9566: Neighbor-wise Collective on A
9568: Input Parameters:
9569: + A - the matrix
9570: . R - the projection matrix
9571: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9572: - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9573: if the result is a dense matrix this is irrelevant
9575: Output Parameters:
9576: . C - the product matrix
9578: Notes:
9579: C will be created and must be destroyed by the user with `MatDestroy()`.
9581: An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9583: This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9584: which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9585: parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9586: We recommend using MatPtAP().
9588: Level: intermediate
9590: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9591: @*/
9592: PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9593: {
9594: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9597: if (scall == MAT_INITIAL_MATRIX) {
9598: MatProductCreate(A, R, NULL, C);
9599: MatProductSetType(*C, MATPRODUCT_RARt);
9600: MatProductSetAlgorithm(*C, "default");
9601: MatProductSetFill(*C, fill);
9603: (*C)->product->api_user = PETSC_TRUE;
9604: MatProductSetFromOptions(*C);
9606: MatProductSymbolic(*C);
9607: } else { /* scall == MAT_REUSE_MATRIX */
9608: MatProductReplaceMats(A, R, NULL, *C);
9609: }
9611: MatProductNumeric(*C);
9612: if (A->symmetric == PETSC_BOOL3_TRUE) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9613: return 0;
9614: }
9616: static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9617: {
9620: if (scall == MAT_INITIAL_MATRIX) {
9621: PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]);
9622: MatProductCreate(A, B, NULL, C);
9623: MatProductSetType(*C, ptype);
9624: MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT);
9625: MatProductSetFill(*C, fill);
9627: (*C)->product->api_user = PETSC_TRUE;
9628: MatProductSetFromOptions(*C);
9629: MatProductSymbolic(*C);
9630: } else { /* scall == MAT_REUSE_MATRIX */
9631: Mat_Product *product = (*C)->product;
9632: PetscBool isdense;
9634: PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "");
9635: if (isdense && product && product->type != ptype) {
9636: MatProductClear(*C);
9637: product = NULL;
9638: }
9639: PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]);
9640: if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9641: if (isdense) {
9642: MatProductCreate_Private(A, B, NULL, *C);
9643: product = (*C)->product;
9644: product->fill = fill;
9645: product->api_user = PETSC_TRUE;
9646: product->clear = PETSC_TRUE;
9648: MatProductSetType(*C, ptype);
9649: MatProductSetFromOptions(*C);
9651: MatProductSymbolic(*C);
9652: } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9653: } else { /* user may change input matrices A or B when REUSE */
9654: MatProductReplaceMats(A, B, NULL, *C);
9655: }
9656: }
9657: MatProductNumeric(*C);
9658: return 0;
9659: }
9661: /*@
9662: MatMatMult - Performs matrix-matrix multiplication C=A*B.
9664: Neighbor-wise Collective on A
9666: Input Parameters:
9667: + A - the left matrix
9668: . B - the right matrix
9669: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9670: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9671: if the result is a dense matrix this is irrelevant
9673: Output Parameters:
9674: . C - the product matrix
9676: Notes:
9677: Unless scall is `MAT_REUSE_MATRIX` C will be created.
9679: `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
9680: call to this function with `MAT_INITIAL_MATRIX`.
9682: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9684: 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`,
9685: rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9687: Example of Usage:
9688: .vb
9689: MatProductCreate(A,B,NULL,&C);
9690: MatProductSetType(C,MATPRODUCT_AB);
9691: MatProductSymbolic(C);
9692: MatProductNumeric(C); // compute C=A * B
9693: MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9694: MatProductNumeric(C);
9695: MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9696: MatProductNumeric(C);
9697: .ve
9699: Level: intermediate
9701: .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9702: @*/
9703: PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9704: {
9705: MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C);
9706: return 0;
9707: }
9709: /*@
9710: MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9712: Neighbor-wise Collective on A
9714: Input Parameters:
9715: + A - the left matrix
9716: . B - the right matrix
9717: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9718: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9720: Output Parameters:
9721: . C - the product matrix
9723: Notes:
9724: C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9726: `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9728: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9729: actually needed.
9731: This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9732: and for pairs of `MATMPIDENSE` matrices.
9734: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
9736: Options Database Keys:
9737: . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9738: first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9739: the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9741: Level: intermediate
9743: .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9744: @*/
9745: PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9746: {
9747: MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C);
9748: if (A == B) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9749: return 0;
9750: }
9752: /*@
9753: MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
9755: Neighbor-wise Collective on A
9757: Input Parameters:
9758: + A - the left matrix
9759: . B - the right matrix
9760: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9761: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9763: Output Parameters:
9764: . C - the product matrix
9766: Notes:
9767: C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9769: `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9771: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
9773: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9774: actually needed.
9776: This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9777: which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices.
9779: Level: intermediate
9781: .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9782: @*/
9783: PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9784: {
9785: MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C);
9786: return 0;
9787: }
9789: /*@
9790: MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
9792: Neighbor-wise Collective on A
9794: Input Parameters:
9795: + A - the left matrix
9796: . B - the middle matrix
9797: . C - the right matrix
9798: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9799: - fill - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DEFAULT` if you do not have a good estimate
9800: if the result is a dense matrix this is irrelevant
9802: Output Parameters:
9803: . D - the product matrix
9805: Notes:
9806: Unless scall is `MAT_REUSE_MATRIX` D will be created.
9808: `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9810: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
9812: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9813: actually needed.
9815: If you have many matrices with the same non-zero structure to multiply, you
9816: should use `MAT_REUSE_MATRIX` in all calls but the first
9818: Level: intermediate
9820: .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9821: @*/
9822: PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
9823: {
9824: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
9827: if (scall == MAT_INITIAL_MATRIX) {
9828: MatProductCreate(A, B, C, D);
9829: MatProductSetType(*D, MATPRODUCT_ABC);
9830: MatProductSetAlgorithm(*D, "default");
9831: MatProductSetFill(*D, fill);
9833: (*D)->product->api_user = PETSC_TRUE;
9834: MatProductSetFromOptions(*D);
9836: ((PetscObject)C)->type_name);
9837: MatProductSymbolic(*D);
9838: } else { /* user may change input matrices when REUSE */
9839: MatProductReplaceMats(A, B, C, *D);
9840: }
9841: MatProductNumeric(*D);
9842: return 0;
9843: }
9845: /*@
9846: MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9848: Collective on mat
9850: Input Parameters:
9851: + mat - the matrix
9852: . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9853: . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
9854: - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9856: Output Parameter:
9857: . matredundant - redundant matrix
9859: Notes:
9860: `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
9861: original matrix has not changed from that last call to MatCreateRedundantMatrix().
9863: This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9864: calling it.
9866: `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
9868: Level: advanced
9870: .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
9871: @*/
9872: PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
9873: {
9874: MPI_Comm comm;
9875: PetscMPIInt size;
9876: PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9877: Mat_Redundant *redund = NULL;
9878: PetscSubcomm psubcomm = NULL;
9879: MPI_Comm subcomm_in = subcomm;
9880: Mat *matseq;
9881: IS isrow, iscol;
9882: PetscBool newsubcomm = PETSC_FALSE;
9885: if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9888: }
9890: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
9891: if (size == 1 || nsubcomm == 1) {
9892: if (reuse == MAT_INITIAL_MATRIX) {
9893: MatDuplicate(mat, MAT_COPY_VALUES, matredundant);
9894: } else {
9896: MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN);
9897: }
9898: return 0;
9899: }
9903: MatCheckPreallocated(mat, 1);
9905: PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0);
9906: if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9907: /* create psubcomm, then get subcomm */
9908: PetscObjectGetComm((PetscObject)mat, &comm);
9909: MPI_Comm_size(comm, &size);
9912: PetscSubcommCreate(comm, &psubcomm);
9913: PetscSubcommSetNumber(psubcomm, nsubcomm);
9914: PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS);
9915: PetscSubcommSetFromOptions(psubcomm);
9916: PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL);
9917: newsubcomm = PETSC_TRUE;
9918: PetscSubcommDestroy(&psubcomm);
9919: }
9921: /* get isrow, iscol and a local sequential matrix matseq[0] */
9922: if (reuse == MAT_INITIAL_MATRIX) {
9923: mloc_sub = PETSC_DECIDE;
9924: nloc_sub = PETSC_DECIDE;
9925: if (bs < 1) {
9926: PetscSplitOwnership(subcomm, &mloc_sub, &M);
9927: PetscSplitOwnership(subcomm, &nloc_sub, &N);
9928: } else {
9929: PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M);
9930: PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N);
9931: }
9932: MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm);
9933: rstart = rend - mloc_sub;
9934: ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow);
9935: ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol);
9936: } else { /* reuse == MAT_REUSE_MATRIX */
9938: /* retrieve subcomm */
9939: PetscObjectGetComm((PetscObject)(*matredundant), &subcomm);
9940: redund = (*matredundant)->redundant;
9941: isrow = redund->isrow;
9942: iscol = redund->iscol;
9943: matseq = redund->matseq;
9944: }
9945: MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq);
9947: /* get matredundant over subcomm */
9948: if (reuse == MAT_INITIAL_MATRIX) {
9949: MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant);
9951: /* create a supporting struct and attach it to C for reuse */
9952: PetscNew(&redund);
9953: (*matredundant)->redundant = redund;
9954: redund->isrow = isrow;
9955: redund->iscol = iscol;
9956: redund->matseq = matseq;
9957: if (newsubcomm) {
9958: redund->subcomm = subcomm;
9959: } else {
9960: redund->subcomm = MPI_COMM_NULL;
9961: }
9962: } else {
9963: MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant);
9964: }
9965: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9966: if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
9967: MatBindToCPU(*matredundant, PETSC_TRUE);
9968: MatSetBindingPropagates(*matredundant, PETSC_TRUE);
9969: }
9970: #endif
9971: PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0);
9972: return 0;
9973: }
9975: /*@C
9976: MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
9977: a given `Mat`. Each submatrix can span multiple procs.
9979: Collective on mat
9981: Input Parameters:
9982: + mat - the matrix
9983: . subcomm - the subcommunicator obtained by MPI_Com_split(comm)
9984: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9986: Output Parameter:
9987: . subMat - 'parallel submatrices each spans a given subcomm
9989: Notes:
9990: The submatrix partition across processors is dictated by 'subComm' a
9991: communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
9992: is not restriced to be grouped with consecutive original ranks.
9994: Due the MPI_Comm_split() usage, the parallel layout of the submatrices
9995: map directly to the layout of the original matrix [wrt the local
9996: row,col partitioning]. So the original 'DiagonalMat' naturally maps
9997: into the 'DiagonalMat' of the subMat, hence it is used directly from
9998: the subMat. However the offDiagMat looses some columns - and this is
9999: reconstructed with `MatSetValues()`
10001: This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10003: Level: advanced
10005: .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10006: @*/
10007: PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10008: {
10009: PetscMPIInt commsize, subCommSize;
10011: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize);
10012: MPI_Comm_size(subComm, &subCommSize);
10016: PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10017: PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10018: PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10019: return 0;
10020: }
10022: /*@
10023: MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10025: Not Collective
10027: Input Parameters:
10028: + mat - matrix to extract local submatrix from
10029: . isrow - local row indices for submatrix
10030: - iscol - local column indices for submatrix
10032: Output Parameter:
10033: . submat - the submatrix
10035: Level: intermediate
10037: Notes:
10038: The submat should be returned with `MatRestoreLocalSubMatrix()`.
10040: Depending on the format of mat, the returned submat may not implement `MatMult()`. Its communicator may be
10041: the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.
10043: The submat always implements `MatSetValuesLocal()`. If isrow and iscol have the same block size, then
10044: `MatSetValuesBlockedLocal()` will also be implemented.
10046: The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10047: Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10049: .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10050: @*/
10051: PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10052: {
10060: if (mat->ops->getlocalsubmatrix) {
10061: PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10062: } else {
10063: MatCreateLocalRef(mat, isrow, iscol, submat);
10064: }
10065: return 0;
10066: }
10068: /*@
10069: MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10071: Not Collective
10073: Input Parameters:
10074: + mat - matrix to extract local submatrix from
10075: . isrow - local row indices for submatrix
10076: . iscol - local column indices for submatrix
10077: - submat - the submatrix
10079: Level: intermediate
10081: .seealso: `MatGetLocalSubMatrix()`
10082: @*/
10083: PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10084: {
10092: if (mat->ops->restorelocalsubmatrix) {
10093: PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10094: } else {
10095: MatDestroy(submat);
10096: }
10097: *submat = NULL;
10098: return 0;
10099: }
10101: /* --------------------------------------------------------*/
10102: /*@
10103: MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10105: Collective on mat
10107: Input Parameter:
10108: . mat - the matrix
10110: Output Parameter:
10111: . is - if any rows have zero diagonals this contains the list of them
10113: Level: developer
10115: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10116: @*/
10117: PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10118: {
10124: if (!mat->ops->findzerodiagonals) {
10125: Vec diag;
10126: const PetscScalar *a;
10127: PetscInt *rows;
10128: PetscInt rStart, rEnd, r, nrow = 0;
10130: MatCreateVecs(mat, &diag, NULL);
10131: MatGetDiagonal(mat, diag);
10132: MatGetOwnershipRange(mat, &rStart, &rEnd);
10133: VecGetArrayRead(diag, &a);
10134: for (r = 0; r < rEnd - rStart; ++r)
10135: if (a[r] == 0.0) ++nrow;
10136: PetscMalloc1(nrow, &rows);
10137: nrow = 0;
10138: for (r = 0; r < rEnd - rStart; ++r)
10139: if (a[r] == 0.0) rows[nrow++] = r + rStart;
10140: VecRestoreArrayRead(diag, &a);
10141: VecDestroy(&diag);
10142: ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is);
10143: } else {
10144: PetscUseTypeMethod(mat, findzerodiagonals, is);
10145: }
10146: return 0;
10147: }
10149: /*@
10150: MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10152: Collective on mat
10154: Input Parameter:
10155: . mat - the matrix
10157: Output Parameter:
10158: . is - contains the list of rows with off block diagonal entries
10160: Level: developer
10162: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10163: @*/
10164: PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10165: {
10171: PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10172: return 0;
10173: }
10175: /*@C
10176: MatInvertBlockDiagonal - Inverts the block diagonal entries.
10178: Collective on mat
10180: Input Parameters:
10181: . mat - the matrix
10183: Output Parameters:
10184: . values - the block inverses in column major order (FORTRAN-like)
10186: Notes:
10187: The size of the blocks is determined by the block size of the matrix.
10189: The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10191: The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10193: Fortran Note:
10194: This routine is not available from Fortran.
10196: Level: advanced
10198: .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10199: @*/
10200: PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10201: {
10205: PetscUseTypeMethod(mat, invertblockdiagonal, values);
10206: return 0;
10207: }
10209: /*@C
10210: MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10212: Collective on mat
10214: Input Parameters:
10215: + mat - the matrix
10216: . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10217: - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10219: Output Parameters:
10220: . values - the block inverses in column major order (FORTRAN-like)
10222: Notes:
10223: Use `MatInvertBlockDiagonal()` if all blocks have the same size
10225: The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10227: Fortran Note:
10228: This routine is not available from Fortran.
10230: Level: advanced
10232: .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10233: @*/
10234: PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10235: {
10239: PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10240: return 0;
10241: }
10243: /*@
10244: MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10246: Collective on Mat
10248: Input Parameters:
10249: + A - the matrix
10250: - C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set.
10252: Note:
10253: The blocksize of the matrix is used to determine the blocks on the diagonal of C
10255: Level: advanced
10257: .seealso: `MatInvertBlockDiagonal()`
10258: @*/
10259: PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10260: {
10261: const PetscScalar *vals;
10262: PetscInt *dnnz;
10263: PetscInt m, rstart, rend, bs, i, j;
10265: MatInvertBlockDiagonal(A, &vals);
10266: MatGetBlockSize(A, &bs);
10267: MatGetLocalSize(A, &m, NULL);
10268: MatSetLayouts(C, A->rmap, A->cmap);
10269: PetscMalloc1(m / bs, &dnnz);
10270: for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10271: MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL);
10272: PetscFree(dnnz);
10273: MatGetOwnershipRange(C, &rstart, &rend);
10274: MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE);
10275: for (i = rstart / bs; i < rend / bs; i++) MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES);
10276: MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY);
10277: MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY);
10278: MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE);
10279: return 0;
10280: }
10282: /*@C
10283: MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10284: via `MatTransposeColoringCreate()`.
10286: Collective on c
10288: Input Parameter:
10289: . c - coloring context
10291: Level: intermediate
10293: .seealso: `MatTransposeColoringCreate()`
10294: @*/
10295: PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10296: {
10297: MatTransposeColoring matcolor = *c;
10299: if (!matcolor) return 0;
10300: if (--((PetscObject)matcolor)->refct > 0) {
10301: matcolor = NULL;
10302: return 0;
10303: }
10305: PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow);
10306: PetscFree(matcolor->rows);
10307: PetscFree(matcolor->den2sp);
10308: PetscFree(matcolor->colorforcol);
10309: PetscFree(matcolor->columns);
10310: if (matcolor->brows > 0) PetscFree(matcolor->lstart);
10311: PetscHeaderDestroy(c);
10312: return 0;
10313: }
10315: /*@C
10316: MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10317: a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10318: `MatTransposeColoring` to sparse B.
10320: Collective on coloring
10322: Input Parameters:
10323: + B - sparse matrix B
10324: . Btdense - symbolic dense matrix B^T
10325: - coloring - coloring context created with `MatTransposeColoringCreate()`
10327: Output Parameter:
10328: . Btdense - dense matrix B^T
10330: Level: developer
10332: Note:
10333: These are used internally for some implementations of `MatRARt()`
10335: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10337: @*/
10338: PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10339: {
10344: (B->ops->transcoloringapplysptoden)(coloring, B, Btdense);
10345: return 0;
10346: }
10348: /*@C
10349: MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10350: a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10351: in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10352: Csp from Cden.
10354: Collective on matcoloring
10356: Input Parameters:
10357: + coloring - coloring context created with `MatTransposeColoringCreate()`
10358: - Cden - matrix product of a sparse matrix and a dense matrix Btdense
10360: Output Parameter:
10361: . Csp - sparse matrix
10363: Level: developer
10365: Note:
10366: These are used internally for some implementations of `MatRARt()`
10368: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10370: @*/
10371: PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10372: {
10377: (Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp);
10378: MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY);
10379: MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY);
10380: return 0;
10381: }
10383: /*@C
10384: MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10386: Collective on mat
10388: Input Parameters:
10389: + mat - the matrix product C
10390: - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10392: Output Parameter:
10393: . color - the new coloring context
10395: Level: intermediate
10397: .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10398: `MatTransColoringApplyDenToSp()`
10399: @*/
10400: PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10401: {
10402: MatTransposeColoring c;
10403: MPI_Comm comm;
10405: PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10406: PetscObjectGetComm((PetscObject)mat, &comm);
10407: PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL);
10409: c->ctype = iscoloring->ctype;
10410: if (mat->ops->transposecoloringcreate) {
10411: PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10412: } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10414: *color = c;
10415: PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10416: return 0;
10417: }
10419: /*@
10420: MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10421: matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10422: same, otherwise it will be larger
10424: Not Collective
10426: Input Parameter:
10427: . A - the matrix
10429: Output Parameter:
10430: . state - the current state
10432: Notes:
10433: You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10434: different matrices
10436: Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10438: Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10440: Level: intermediate
10442: .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10443: @*/
10444: PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10445: {
10447: *state = mat->nonzerostate;
10448: return 0;
10449: }
10451: /*@
10452: MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10453: matrices from each processor
10455: Collective
10457: Input Parameters:
10458: + comm - the communicators the parallel matrix will live on
10459: . seqmat - the input sequential matrices
10460: . n - number of local columns (or `PETSC_DECIDE`)
10461: - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10463: Output Parameter:
10464: . mpimat - the parallel matrix generated
10466: Level: developer
10468: Note:
10469: The number of columns of the matrix in EACH processor MUST be the same.
10471: .seealso: `Mat`
10472: @*/
10473: PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10474: {
10475: PetscMPIInt size;
10477: MPI_Comm_size(comm, &size);
10478: if (size == 1) {
10479: if (reuse == MAT_INITIAL_MATRIX) {
10480: MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat);
10481: } else {
10482: MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN);
10483: }
10484: return 0;
10485: }
10489: PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0);
10490: (*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat);
10491: PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0);
10492: return 0;
10493: }
10495: /*@
10496: MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10498: Collective on A
10500: Input Parameters:
10501: + A - the matrix to create subdomains from
10502: - N - requested number of subdomains
10504: Output Parameters:
10505: + n - number of subdomains resulting on this rank
10506: - iss - `IS` list with indices of subdomains on this rank
10508: Level: advanced
10510: Note:
10511: The number of subdomains must be smaller than the communicator size
10513: .seealso: `Mat`, `IS`
10514: @*/
10515: PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10516: {
10517: MPI_Comm comm, subcomm;
10518: PetscMPIInt size, rank, color;
10519: PetscInt rstart, rend, k;
10521: PetscObjectGetComm((PetscObject)A, &comm);
10522: MPI_Comm_size(comm, &size);
10523: MPI_Comm_rank(comm, &rank);
10525: *n = 1;
10526: k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10527: color = rank / k;
10528: MPI_Comm_split(comm, color, rank, &subcomm);
10529: PetscMalloc1(1, iss);
10530: MatGetOwnershipRange(A, &rstart, &rend);
10531: ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]);
10532: MPI_Comm_free(&subcomm);
10533: return 0;
10534: }
10536: /*@
10537: MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10539: If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10540: If they are not the same, uses `MatMatMatMult()`.
10542: Once the coarse grid problem is constructed, correct for interpolation operators
10543: that are not of full rank, which can legitimately happen in the case of non-nested
10544: geometric multigrid.
10546: Input Parameters:
10547: + restrct - restriction operator
10548: . dA - fine grid matrix
10549: . interpolate - interpolation operator
10550: . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10551: - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10553: Output Parameters:
10554: . A - the Galerkin coarse matrix
10556: Options Database Key:
10557: . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10559: Level: developer
10561: .seealso: `MatPtAP()`, `MatMatMatMult()`
10562: @*/
10563: PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10564: {
10565: IS zerorows;
10566: Vec diag;
10569: /* Construct the coarse grid matrix */
10570: if (interpolate == restrct) {
10571: MatPtAP(dA, interpolate, reuse, fill, A);
10572: } else {
10573: MatMatMatMult(restrct, dA, interpolate, reuse, fill, A);
10574: }
10576: /* If the interpolation matrix is not of full rank, A will have zero rows.
10577: This can legitimately happen in the case of non-nested geometric multigrid.
10578: In that event, we set the rows of the matrix to the rows of the identity,
10579: ignoring the equations (as the RHS will also be zero). */
10581: MatFindZeroRows(*A, &zerorows);
10583: if (zerorows != NULL) { /* if there are any zero rows */
10584: MatCreateVecs(*A, &diag, NULL);
10585: MatGetDiagonal(*A, diag);
10586: VecISSet(diag, zerorows, 1.0);
10587: MatDiagonalSet(*A, diag, INSERT_VALUES);
10588: VecDestroy(&diag);
10589: ISDestroy(&zerorows);
10590: }
10591: return 0;
10592: }
10594: /*@C
10595: MatSetOperation - Allows user to set a matrix operation for any matrix type
10597: Logically Collective on mat
10599: Input Parameters:
10600: + mat - the matrix
10601: . op - the name of the operation
10602: - f - the function that provides the operation
10604: Level: developer
10606: Usage:
10607: $ extern PetscErrorCode usermult(Mat,Vec,Vec);
10608: $ MatCreateXXX(comm,...&A;
10609: $ MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult;
10611: Notes:
10612: See the file include/petscmat.h for a complete list of matrix
10613: operations, which all have the form MATOP_<OPERATION>, where
10614: <OPERATION> is the name (in all capital letters) of the
10615: user interface routine (e.g., MatMult() -> MATOP_MULT).
10617: All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10618: sequence as the usual matrix interface routines, since they
10619: are intended to be accessed via the usual matrix interface
10620: routines, e.g.,
10621: $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10623: In particular each function MUST return an error code of 0 on success and
10624: nonzero on failure.
10626: This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10628: .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10629: @*/
10630: PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10631: {
10633: if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10634: (((void (**)(void))mat->ops)[op]) = f;
10635: return 0;
10636: }
10638: /*@C
10639: MatGetOperation - Gets a matrix operation for any matrix type.
10641: Not Collective
10643: Input Parameters:
10644: + mat - the matrix
10645: - op - the name of the operation
10647: Output Parameter:
10648: . f - the function that provides the operation
10650: Level: developer
10652: Usage:
10653: $ PetscErrorCode (*usermult)(Mat,Vec,Vec);
10654: $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10656: Notes:
10657: See the file include/petscmat.h for a complete list of matrix
10658: operations, which all have the form MATOP_<OPERATION>, where
10659: <OPERATION> is the name (in all capital letters) of the
10660: user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10662: This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10664: .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10665: @*/
10666: PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10667: {
10669: *f = (((void (**)(void))mat->ops)[op]);
10670: return 0;
10671: }
10673: /*@
10674: MatHasOperation - Determines whether the given matrix supports the particular operation.
10676: Not Collective
10678: Input Parameters:
10679: + mat - the matrix
10680: - op - the operation, for example, `MATOP_GET_DIAGONAL`
10682: Output Parameter:
10683: . has - either `PETSC_TRUE` or `PETSC_FALSE`
10685: Level: advanced
10687: Note:
10688: See the file include/petscmat.h for a complete list of matrix
10689: operations, which all have the form MATOP_<OPERATION>, where
10690: <OPERATION> is the name (in all capital letters) of the
10691: user-level routine. E.g., `MatNorm()` -> `MATOP_NORM`.
10693: .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10694: @*/
10695: PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10696: {
10699: if (mat->ops->hasoperation) {
10700: PetscUseTypeMethod(mat, hasoperation, op, has);
10701: } else {
10702: if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10703: else {
10704: *has = PETSC_FALSE;
10705: if (op == MATOP_CREATE_SUBMATRIX) {
10706: PetscMPIInt size;
10708: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
10709: if (size == 1) MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has);
10710: }
10711: }
10712: }
10713: return 0;
10714: }
10716: /*@
10717: MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
10719: Collective on mat
10721: Input Parameters:
10722: . mat - the matrix
10724: Output Parameter:
10725: . cong - either `PETSC_TRUE` or `PETSC_FALSE`
10727: Level: beginner
10729: .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10730: @*/
10731: PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10732: {
10736: if (!mat->rmap || !mat->cmap) {
10737: *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10738: return 0;
10739: }
10740: if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10741: PetscLayoutSetUp(mat->rmap);
10742: PetscLayoutSetUp(mat->cmap);
10743: PetscLayoutCompare(mat->rmap, mat->cmap, cong);
10744: if (*cong) mat->congruentlayouts = 1;
10745: else mat->congruentlayouts = 0;
10746: } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10747: return 0;
10748: }
10750: PetscErrorCode MatSetInf(Mat A)
10751: {
10752: PetscUseTypeMethod(A, setinf);
10753: return 0;
10754: }
10756: /*C
10757: 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
10758: and possibly removes small values from the graph structure.
10760: Collective on mat
10762: Input Parameters:
10763: + A - the matrix
10764: . sym - `PETSC_TRUE` indicates that the graph should be symmetrized
10765: . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
10766: - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
10768: Output Parameter:
10769: . graph - the resulting graph
10771: Level: advanced
10773: .seealso: `MatCreate()`, `PCGAMG`
10774: */
10775: PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
10776: {
10780: PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
10781: return 0;
10782: }