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
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
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
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
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
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
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
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
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
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: Level: advanced
835: Fortran Note:
836: On the fortran side, the user should pass in a string 'prefix' of
837: sufficient length to hold the prefix.
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 Key:
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
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);
1049: PetscViewerGetFormat(viewer, &format);
1050: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
1051: if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) return 0;
1053: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring);
1054: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
1055: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws);
1058: PetscLogEventBegin(MAT_View, mat, viewer, 0, 0);
1059: if (isascii) {
1060: if (!mat->preallocated) {
1061: PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n");
1062: return 0;
1063: }
1064: if (!mat->assembled) {
1065: PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n");
1066: return 0;
1067: }
1068: PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer);
1069: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1070: MatNullSpace nullsp, transnullsp;
1072: PetscViewerASCIIPushTab(viewer);
1073: MatGetSize(mat, &rows, &cols);
1074: MatGetBlockSizes(mat, &rbs, &cbs);
1075: if (rbs != 1 || cbs != 1) {
1076: if (rbs != cbs) PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs);
1077: else PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs);
1078: } else PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols);
1079: if (mat->factortype) {
1080: MatSolverType solver;
1081: MatFactorGetSolverType(mat, &solver);
1082: PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver);
1083: }
1084: if (mat->ops->getinfo) {
1085: MatInfo info;
1086: MatGetInfo(mat, MAT_GLOBAL_SUM, &info);
1087: PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated);
1088: if (!mat->factortype) PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs);
1089: }
1090: MatGetNullSpace(mat, &nullsp);
1091: MatGetTransposeNullSpace(mat, &transnullsp);
1092: if (nullsp) PetscViewerASCIIPrintf(viewer, " has attached null space\n");
1093: if (transnullsp && transnullsp != nullsp) PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n");
1094: MatGetNearNullSpace(mat, &nullsp);
1095: if (nullsp) PetscViewerASCIIPrintf(viewer, " has attached near null space\n");
1096: PetscViewerASCIIPushTab(viewer);
1097: MatProductView(mat, viewer);
1098: PetscViewerASCIIPopTab(viewer);
1099: }
1100: } else if (issaws) {
1101: #if defined(PETSC_HAVE_SAWS)
1102: PetscMPIInt rank;
1104: PetscObjectName((PetscObject)mat);
1105: MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1106: if (!((PetscObject)mat)->amsmem && rank == 0) PetscObjectViewSAWs((PetscObject)mat, viewer);
1107: #endif
1108: } else if (isstring) {
1109: const char *type;
1110: MatGetType(mat, &type);
1111: PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type);
1112: PetscTryTypeMethod(mat, view, viewer);
1113: }
1114: if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1115: PetscViewerASCIIPushTab(viewer);
1116: PetscUseTypeMethod(mat, viewnative, viewer);
1117: PetscViewerASCIIPopTab(viewer);
1118: } else if (mat->ops->view) {
1119: PetscViewerASCIIPushTab(viewer);
1120: PetscUseTypeMethod(mat, view, viewer);
1121: PetscViewerASCIIPopTab(viewer);
1122: }
1123: if (isascii) {
1124: PetscViewerGetFormat(viewer, &format);
1125: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscViewerASCIIPopTab(viewer);
1126: }
1127: PetscLogEventEnd(MAT_View, mat, viewer, 0, 0);
1128: return 0;
1129: }
1131: #if defined(PETSC_USE_DEBUG)
1132: #include <../src/sys/totalview/tv_data_display.h>
1133: PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1134: {
1135: TV_add_row("Local rows", "int", &mat->rmap->n);
1136: TV_add_row("Local columns", "int", &mat->cmap->n);
1137: TV_add_row("Global rows", "int", &mat->rmap->N);
1138: TV_add_row("Global columns", "int", &mat->cmap->N);
1139: TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1140: return TV_format_OK;
1141: }
1142: #endif
1144: /*@C
1145: MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1146: with `MatView()`. The matrix format is determined from the options database.
1147: Generates a parallel MPI matrix if the communicator has more than one
1148: processor. The default matrix type is `MATAIJ`.
1150: Collective
1152: Input Parameters:
1153: + mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1154: or some related function before a call to `MatLoad()`
1155: - viewer - binary/HDF5 file viewer
1157: Options Database Keys:
1158: Used with block matrix formats (`MATSEQBAIJ`, ...) to specify
1159: block size
1160: . -matload_block_size <bs> - set block size
1162: Level: beginner
1164: Notes:
1165: If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1166: `Mat` before calling this routine if you wish to set it from the options database.
1168: `MatLoad()` automatically loads into the options database any options
1169: given in the file filename.info where filename is the name of the file
1170: that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1171: file will be ignored if you use the -viewer_binary_skip_info option.
1173: If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1174: sets the default matrix type AIJ and sets the local and global sizes.
1175: If type and/or size is already set, then the same are used.
1177: In parallel, each processor can load a subset of rows (or the
1178: entire matrix). This routine is especially useful when a large
1179: matrix is stored on disk and only part of it is desired on each
1180: processor. For example, a parallel solver may access only some of
1181: the rows from each processor. The algorithm used here reads
1182: relatively small blocks of data rather than reading the entire
1183: matrix and then subsetting it.
1185: Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1186: Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1187: or the sequence like
1188: .vb
1189: `PetscViewer` v;
1190: `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1191: `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1192: `PetscViewerSetFromOptions`(v);
1193: `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1194: `PetscViewerFileSetName`(v,"datafile");
1195: .ve
1196: The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1197: $ -viewer_type {binary,hdf5}
1199: See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1200: and src/mat/tutorials/ex10.c with the second approach.
1202: Notes about the PETSc binary format:
1203: In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1204: is read onto rank 0 and then shipped to its destination rank, one after another.
1205: Multiple objects, both matrices and vectors, can be stored within the same file.
1206: Their PetscObject name is ignored; they are loaded in the order of their storage.
1208: Most users should not need to know the details of the binary storage
1209: format, since `MatLoad()` and `MatView()` completely hide these details.
1210: But for anyone who's interested, the standard binary matrix storage
1211: format is
1213: $ PetscInt MAT_FILE_CLASSID
1214: $ PetscInt number of rows
1215: $ PetscInt number of columns
1216: $ PetscInt total number of nonzeros
1217: $ PetscInt *number nonzeros in each row
1218: $ PetscInt *column indices of all nonzeros (starting index is zero)
1219: $ PetscScalar *values of all nonzeros
1221: PETSc automatically does the byte swapping for
1222: machines that store the bytes reversed, e.g. DEC alpha, freebsd,
1223: Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1224: read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1225: and `PetscBinaryWrite()` to see how this may be done.
1227: Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1228: In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1229: Each processor's chunk is loaded independently by its owning rank.
1230: Multiple objects, both matrices and vectors, can be stored within the same file.
1231: They are looked up by their PetscObject name.
1233: As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1234: by default the same structure and naming of the AIJ arrays and column count
1235: within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1236: $ save example.mat A b -v7.3
1237: can be directly read by this routine (see Reference 1 for details).
1238: Note that depending on your MATLAB version, this format might be a default,
1239: otherwise you can set it as default in Preferences.
1241: Unless -nocompression flag is used to save the file in MATLAB,
1242: PETSc must be configured with ZLIB package.
1244: See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1246: Current HDF5 (MAT-File) limitations:
1247: This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1249: Corresponding `MatView()` is not yet implemented.
1251: The loaded matrix is actually a transpose of the original one in MATLAB,
1252: unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1253: With this format, matrix is automatically transposed by PETSc,
1254: unless the matrix is marked as SPD or symmetric
1255: (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1257: References:
1258: . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1260: .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1261: @*/
1262: PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1263: {
1264: PetscBool flg;
1269: if (!((PetscObject)mat)->type_name) MatSetType(mat, MATAIJ);
1271: flg = PETSC_FALSE;
1272: PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL);
1273: if (flg) {
1274: MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE);
1275: MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE);
1276: }
1277: flg = PETSC_FALSE;
1278: PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL);
1279: if (flg) MatSetOption(mat, MAT_SPD, PETSC_TRUE);
1281: PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0);
1282: PetscUseTypeMethod(mat, load, viewer);
1283: PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0);
1284: return 0;
1285: }
1287: static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1288: {
1289: Mat_Redundant *redund = *redundant;
1291: if (redund) {
1292: if (redund->matseq) { /* via MatCreateSubMatrices() */
1293: ISDestroy(&redund->isrow);
1294: ISDestroy(&redund->iscol);
1295: MatDestroySubMatrices(1, &redund->matseq);
1296: } else {
1297: PetscFree2(redund->send_rank, redund->recv_rank);
1298: PetscFree(redund->sbuf_j);
1299: PetscFree(redund->sbuf_a);
1300: for (PetscInt i = 0; i < redund->nrecvs; i++) {
1301: PetscFree(redund->rbuf_j[i]);
1302: PetscFree(redund->rbuf_a[i]);
1303: }
1304: PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a);
1305: }
1307: if (redund->subcomm) PetscCommDestroy(&redund->subcomm);
1308: PetscFree(redund);
1309: }
1310: return 0;
1311: }
1313: /*@C
1314: MatDestroy - Frees space taken by a matrix.
1316: Collective on A
1318: Input Parameter:
1319: . A - the matrix
1321: Level: beginner
1323: Developer Note:
1324: Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1325: `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1326: `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1327: if changes are needed here.
1329: .seealso: `Mat`, `MatCreate()`
1330: @*/
1331: PetscErrorCode MatDestroy(Mat *A)
1332: {
1333: if (!*A) return 0;
1335: if (--((PetscObject)(*A))->refct > 0) {
1336: *A = NULL;
1337: return 0;
1338: }
1340: /* if memory was published with SAWs then destroy it */
1341: PetscObjectSAWsViewOff((PetscObject)*A);
1342: PetscTryTypeMethod((*A), destroy);
1344: PetscFree((*A)->factorprefix);
1345: PetscFree((*A)->defaultvectype);
1346: PetscFree((*A)->defaultrandtype);
1347: PetscFree((*A)->bsizes);
1348: PetscFree((*A)->solvertype);
1349: for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscFree((*A)->preferredordering[i]);
1350: if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1351: MatDestroy_Redundant(&(*A)->redundant);
1352: MatProductClear(*A);
1353: MatNullSpaceDestroy(&(*A)->nullsp);
1354: MatNullSpaceDestroy(&(*A)->transnullsp);
1355: MatNullSpaceDestroy(&(*A)->nearnullsp);
1356: MatDestroy(&(*A)->schur);
1357: PetscLayoutDestroy(&(*A)->rmap);
1358: PetscLayoutDestroy(&(*A)->cmap);
1359: PetscHeaderDestroy(A);
1360: return 0;
1361: }
1363: /*@C
1364: MatSetValues - Inserts or adds a block of values into a matrix.
1365: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1366: MUST be called after all calls to `MatSetValues()` have been completed.
1368: Not Collective
1370: Input Parameters:
1371: + mat - the matrix
1372: . v - a logically two-dimensional array of values
1373: . m, idxm - the number of rows and their global indices
1374: . n, idxn - the number of columns and their global indices
1375: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1377: Notes:
1378: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1379: `MatSetUp()` before using this routine
1381: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1383: Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1384: options cannot be mixed without intervening calls to the assembly
1385: routines.
1387: `MatSetValues()` uses 0-based row and column numbers in Fortran
1388: as well as in C.
1390: Negative indices may be passed in idxm and idxn, these rows and columns are
1391: simply ignored. This allows easily inserting element stiffness matrices
1392: with homogeneous Dirchlet boundary conditions that you don't want represented
1393: in the matrix.
1395: Efficiency Alert:
1396: The routine `MatSetValuesBlocked()` may offer much better efficiency
1397: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1399: Level: beginner
1401: Developer Note:
1402: This is labeled with C so does not automatically generate Fortran stubs and interfaces
1403: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1405: .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1406: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1407: @*/
1408: PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1409: {
1413: if (!m || !n) return 0; /* no values to insert */
1416: MatCheckPreallocated(mat, 1);
1418: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1421: if (PetscDefined(USE_DEBUG)) {
1422: PetscInt i, j;
1425: for (i = 0; i < m; i++) {
1426: for (j = 0; j < n; j++) {
1427: if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1428: #if defined(PETSC_USE_COMPLEX)
1429: 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]);
1430: #else
1431: 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]);
1432: #endif
1433: }
1434: }
1437: }
1439: if (mat->assembled) {
1440: mat->was_assembled = PETSC_TRUE;
1441: mat->assembled = PETSC_FALSE;
1442: }
1443: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1444: PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1445: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1446: return 0;
1447: }
1449: /*@C
1450: MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1451: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1452: MUST be called after all calls to `MatSetValues()` have been completed.
1454: Not Collective
1456: Input Parameters:
1457: + mat - the matrix
1458: . v - a logically two-dimensional array of values
1459: . ism - the rows to provide
1460: . isn - the columns to provide
1461: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1463: Level: beginner
1465: Notes:
1466: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1467: `MatSetUp()` before using this routine
1469: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1471: Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1472: options cannot be mixed without intervening calls to the assembly
1473: routines.
1475: `MatSetValues()` uses 0-based row and column numbers in Fortran
1476: as well as in C.
1478: Negative indices may be passed in ism and isn, these rows and columns are
1479: simply ignored. This allows easily inserting element stiffness matrices
1480: with homogeneous Dirchlet boundary conditions that you don't want represented
1481: in the matrix.
1483: Efficiency Alert:
1484: The routine `MatSetValuesBlocked()` may offer much better efficiency
1485: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1487: This is currently not optimized for any particular `ISType`
1489: Developer Notes:
1490: This is labeled with C so does not automatically generate Fortran stubs and interfaces
1491: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1493: .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1494: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1495: @*/
1496: PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1497: {
1498: PetscInt m, n;
1499: const PetscInt *rows, *cols;
1503: ISGetIndices(ism, &rows);
1504: ISGetIndices(isn, &cols);
1505: ISGetLocalSize(ism, &m);
1506: ISGetLocalSize(isn, &n);
1507: MatSetValues(mat, m, rows, n, cols, v, addv);
1508: ISRestoreIndices(ism, &rows);
1509: ISRestoreIndices(isn, &cols);
1510: return 0;
1511: }
1513: /*@
1514: MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1515: values into a matrix
1517: Not Collective
1519: Input Parameters:
1520: + mat - the matrix
1521: . row - the (block) row to set
1522: - v - a logically two-dimensional array of values
1524: Notes:
1525: By the values, v, are column-oriented (for the block version) and sorted
1527: All the nonzeros in the row must be provided
1529: The matrix must have previously had its column indices set
1531: The row must belong to this process
1533: Level: intermediate
1535: .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1536: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1537: @*/
1538: PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1539: {
1540: PetscInt globalrow;
1545: ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow);
1546: MatSetValuesRow(mat, globalrow, v);
1547: return 0;
1548: }
1550: /*@
1551: MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1552: values into a matrix
1554: Not Collective
1556: Input Parameters:
1557: + mat - the matrix
1558: . row - the (block) row to set
1559: - 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
1561: Notes:
1562: The values, v, are column-oriented for the block version.
1564: All the nonzeros in the row must be provided
1566: THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1568: The row must belong to this process
1570: Level: advanced
1572: .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1573: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1574: @*/
1575: PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1576: {
1580: MatCheckPreallocated(mat, 1);
1584: mat->insertmode = INSERT_VALUES;
1586: if (mat->assembled) {
1587: mat->was_assembled = PETSC_TRUE;
1588: mat->assembled = PETSC_FALSE;
1589: }
1590: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1591: PetscUseTypeMethod(mat, setvaluesrow, row, v);
1592: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1593: return 0;
1594: }
1596: /*@
1597: MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1598: Using structured grid indexing
1600: Not Collective
1602: Input Parameters:
1603: + mat - the matrix
1604: . m - number of rows being entered
1605: . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1606: . n - number of columns being entered
1607: . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1608: . v - a logically two-dimensional array of values
1609: - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1611: Level: beginner
1613: Notes:
1614: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1616: Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1617: options cannot be mixed without intervening calls to the assembly
1618: routines.
1620: The grid coordinates are across the entire grid, not just the local portion
1622: `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1623: as well as in C.
1625: For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1627: In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1628: or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1630: The columns and rows in the stencil passed in MUST be contained within the
1631: ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1632: if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1633: local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1634: first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1636: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1637: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1638: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1639: `DM_BOUNDARY_PERIODIC` boundary type.
1641: 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
1642: a single value per point) you can skip filling those indices.
1644: Inspired by the structured grid interface to the HYPRE package
1645: (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1647: Efficiency Alert:
1648: The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1649: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1651: Fortran Note:
1652: In Fortran idxm and idxn should be declared as
1653: $ MatStencil idxm(4,m),idxn(4,n)
1654: and the values inserted using
1655: .vb
1656: idxm(MatStencil_i,1) = i
1657: idxm(MatStencil_j,1) = j
1658: idxm(MatStencil_k,1) = k
1659: idxm(MatStencil_c,1) = c
1660: etc
1661: .ve
1663: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1664: `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1665: @*/
1666: PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1667: {
1668: PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1669: PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1670: PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1672: if (!m || !n) return 0; /* no values to insert */
1678: if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1679: jdxm = buf;
1680: jdxn = buf + m;
1681: } else {
1682: PetscMalloc2(m, &bufm, n, &bufn);
1683: jdxm = bufm;
1684: jdxn = bufn;
1685: }
1686: for (i = 0; i < m; i++) {
1687: for (j = 0; j < 3 - sdim; j++) dxm++;
1688: tmp = *dxm++ - starts[0];
1689: for (j = 0; j < dim - 1; j++) {
1690: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1691: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1692: }
1693: if (mat->stencil.noc) dxm++;
1694: jdxm[i] = tmp;
1695: }
1696: for (i = 0; i < n; i++) {
1697: for (j = 0; j < 3 - sdim; j++) dxn++;
1698: tmp = *dxn++ - starts[0];
1699: for (j = 0; j < dim - 1; j++) {
1700: if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1701: else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1702: }
1703: if (mat->stencil.noc) dxn++;
1704: jdxn[i] = tmp;
1705: }
1706: MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv);
1707: PetscFree2(bufm, bufn);
1708: return 0;
1709: }
1711: /*@
1712: MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1713: Using structured grid indexing
1715: Not Collective
1717: Input Parameters:
1718: + mat - the matrix
1719: . m - number of rows being entered
1720: . idxm - grid coordinates for matrix rows being entered
1721: . n - number of columns being entered
1722: . idxn - grid coordinates for matrix columns being entered
1723: . v - a logically two-dimensional array of values
1724: - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1726: Level: beginner
1728: Notes:
1729: By default the values, v, are row-oriented and unsorted.
1730: See `MatSetOption()` for other options.
1732: Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1733: options cannot be mixed without intervening calls to the assembly
1734: routines.
1736: The grid coordinates are across the entire grid, not just the local portion
1738: `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1739: as well as in C.
1741: For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1743: In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1744: or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1746: The columns and rows in the stencil passed in MUST be contained within the
1747: ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1748: if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1749: local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1750: first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1752: Negative indices may be passed in idxm and idxn, these rows and columns are
1753: simply ignored. This allows easily inserting element stiffness matrices
1754: with homogeneous Dirchlet boundary conditions that you don't want represented
1755: in the matrix.
1757: Inspired by the structured grid interface to the HYPRE package
1758: (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1760: Fortran Note:
1761: In Fortran idxm and idxn should be declared as
1762: $ MatStencil idxm(4,m),idxn(4,n)
1763: and the values inserted using
1764: .vb
1765: idxm(MatStencil_i,1) = i
1766: idxm(MatStencil_j,1) = j
1767: idxm(MatStencil_k,1) = k
1768: etc
1769: .ve
1771: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1772: `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1773: `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1774: @*/
1775: PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1776: {
1777: PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1778: PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1779: PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1781: if (!m || !n) return 0; /* no values to insert */
1788: if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1789: jdxm = buf;
1790: jdxn = buf + m;
1791: } else {
1792: PetscMalloc2(m, &bufm, n, &bufn);
1793: jdxm = bufm;
1794: jdxn = bufn;
1795: }
1796: for (i = 0; i < m; i++) {
1797: for (j = 0; j < 3 - sdim; j++) dxm++;
1798: tmp = *dxm++ - starts[0];
1799: for (j = 0; j < sdim - 1; j++) {
1800: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1801: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1802: }
1803: dxm++;
1804: jdxm[i] = tmp;
1805: }
1806: for (i = 0; i < n; i++) {
1807: for (j = 0; j < 3 - sdim; j++) dxn++;
1808: tmp = *dxn++ - starts[0];
1809: for (j = 0; j < sdim - 1; j++) {
1810: if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1811: else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1812: }
1813: dxn++;
1814: jdxn[i] = tmp;
1815: }
1816: MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv);
1817: PetscFree2(bufm, bufn);
1818: return 0;
1819: }
1821: /*@
1822: MatSetStencil - Sets the grid information for setting values into a matrix via
1823: `MatSetValuesStencil()`
1825: Not Collective
1827: Input Parameters:
1828: + mat - the matrix
1829: . dim - dimension of the grid 1, 2, or 3
1830: . dims - number of grid points in x, y, and z direction, including ghost points on your processor
1831: . starts - starting point of ghost nodes on your processor in x, y, and z direction
1832: - dof - number of degrees of freedom per node
1834: Notes:
1835: Inspired by the structured grid interface to the HYPRE package
1836: (www.llnl.gov/CASC/hyper)
1838: For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1839: user.
1841: Level: beginner
1843: .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1844: `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1845: @*/
1846: PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1847: {
1852: mat->stencil.dim = dim + (dof > 1);
1853: for (PetscInt i = 0; i < dim; i++) {
1854: mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */
1855: mat->stencil.starts[i] = starts[dim - i - 1];
1856: }
1857: mat->stencil.dims[dim] = dof;
1858: mat->stencil.starts[dim] = 0;
1859: mat->stencil.noc = (PetscBool)(dof == 1);
1860: return 0;
1861: }
1863: /*@C
1864: MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1866: Not Collective
1868: Input Parameters:
1869: + mat - the matrix
1870: . v - a logically two-dimensional array of values
1871: . m, idxm - the number of block rows and their global block indices
1872: . n, idxn - the number of block columns and their global block indices
1873: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1875: Level: intermediate
1877: Notes:
1878: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1879: MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1881: The m and n count the NUMBER of blocks in the row direction and column direction,
1882: NOT the total number of rows/columns; for example, if the block size is 2 and
1883: you are passing in values for rows 2,3,4,5 then m would be 2 (not 4).
1884: The values in idxm would be 1 2; that is the first index for each block divided by
1885: the block size.
1887: Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1888: preallocating it).
1890: By default the values, v, are row-oriented, so the layout of
1891: v is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1893: Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1894: options cannot be mixed without intervening calls to the assembly
1895: routines.
1897: `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1898: as well as in C.
1900: Negative indices may be passed in idxm and idxn, these rows and columns are
1901: simply ignored. This allows easily inserting element stiffness matrices
1902: with homogeneous Dirchlet boundary conditions that you don't want represented
1903: in the matrix.
1905: Each time an entry is set within a sparse matrix via `MatSetValues()`,
1906: internal searching must be done to determine where to place the
1907: data in the matrix storage space. By instead inserting blocks of
1908: entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1909: reduced.
1911: Example:
1912: .vb
1913: Suppose m=n=2 and block size(bs) = 2 The array is
1915: 1 2 | 3 4
1916: 5 6 | 7 8
1917: - - - | - - -
1918: 9 10 | 11 12
1919: 13 14 | 15 16
1921: v[] should be passed in like
1922: v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1924: If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1925: v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1926: .ve
1928: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1929: @*/
1930: PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1931: {
1935: if (!m || !n) return 0; /* no values to insert */
1938: MatCheckPreallocated(mat, 1);
1939: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1941: if (PetscDefined(USE_DEBUG)) {
1944: }
1945: if (PetscDefined(USE_DEBUG)) {
1946: PetscInt rbs, cbs, M, N, i;
1947: MatGetBlockSizes(mat, &rbs, &cbs);
1948: MatGetSize(mat, &M, &N);
1951: }
1952: if (mat->assembled) {
1953: mat->was_assembled = PETSC_TRUE;
1954: mat->assembled = PETSC_FALSE;
1955: }
1956: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1957: if (mat->ops->setvaluesblocked) {
1958: PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1959: } else {
1960: PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1961: PetscInt i, j, bs, cbs;
1963: MatGetBlockSizes(mat, &bs, &cbs);
1964: if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1965: iidxm = buf;
1966: iidxn = buf + m * bs;
1967: } else {
1968: PetscMalloc2(m * bs, &bufr, n * cbs, &bufc);
1969: iidxm = bufr;
1970: iidxn = bufc;
1971: }
1972: for (i = 0; i < m; i++) {
1973: for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
1974: }
1975: if (m != n || bs != cbs || idxm != idxn) {
1976: for (i = 0; i < n; i++) {
1977: for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
1978: }
1979: } else iidxn = iidxm;
1980: MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv);
1981: PetscFree2(bufr, bufc);
1982: }
1983: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1984: return 0;
1985: }
1987: /*@C
1988: MatGetValues - Gets a block of local values from a matrix.
1990: Not Collective; can only return values that are owned by the give process
1992: Input Parameters:
1993: + mat - the matrix
1994: . v - a logically two-dimensional array for storing the values
1995: . m, idxm - the number of rows and their global indices
1996: - n, idxn - the number of columns and their global indices
1998: Notes:
1999: The user must allocate space (m*n `PetscScalar`s) for the values, v.
2000: The values, v, are then returned in a row-oriented format,
2001: analogous to that used by default in `MatSetValues()`.
2003: `MatGetValues()` uses 0-based row and column numbers in
2004: Fortran as well as in C.
2006: `MatGetValues()` requires that the matrix has been assembled
2007: with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to
2008: `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2009: without intermediate matrix assembly.
2011: Negative row or column indices will be ignored and those locations in v[] will be
2012: left unchanged.
2014: For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2015: That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2016: from `MatGetOwnershipRange`(mat,&rstart,&rend).
2018: Level: advanced
2020: .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2021: @*/
2022: PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2023: {
2026: if (!m || !n) return 0;
2032: MatCheckPreallocated(mat, 1);
2034: PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2035: PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2036: PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2037: return 0;
2038: }
2040: /*@C
2041: MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2042: defined previously by `MatSetLocalToGlobalMapping()`
2044: Not Collective
2046: Input Parameters:
2047: + mat - the matrix
2048: . nrow, irow - number of rows and their local indices
2049: - ncol, icol - number of columns and their local indices
2051: Output Parameter:
2052: . y - a logically two-dimensional array of values
2054: Level: advanced
2056: Notes:
2057: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2059: 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,
2060: are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2061: determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2062: with `MatSetLocalToGlobalMapping()`.
2064: Developer Note:
2065: This is labelled with C so does not automatically generate Fortran stubs and interfaces
2066: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2068: .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2069: `MatSetValuesLocal()`, `MatGetValues()`
2070: @*/
2071: PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2072: {
2076: MatCheckPreallocated(mat, 1);
2077: if (!nrow || !ncol) return 0; /* no values to retrieve */
2080: if (PetscDefined(USE_DEBUG)) {
2083: }
2085: PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2086: if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2087: else {
2088: PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2089: if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2090: irowm = buf;
2091: icolm = buf + nrow;
2092: } else {
2093: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2094: irowm = bufr;
2095: icolm = bufc;
2096: }
2099: ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm);
2100: ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm);
2101: MatGetValues(mat, nrow, irowm, ncol, icolm, y);
2102: PetscFree2(bufr, bufc);
2103: }
2104: PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2105: return 0;
2106: }
2108: /*@
2109: MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2110: the same size. Currently, this can only be called once and creates the given matrix.
2112: Not Collective
2114: Input Parameters:
2115: + mat - the matrix
2116: . nb - the number of blocks
2117: . bs - the number of rows (and columns) in each block
2118: . rows - a concatenation of the rows for each block
2119: - v - a concatenation of logically two-dimensional arrays of values
2121: Note:
2122: `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2124: In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2126: Level: advanced
2128: .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2129: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2130: @*/
2131: PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2132: {
2137: PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2139: PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0);
2140: if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2141: else {
2142: for (PetscInt b = 0; b < nb; ++b) MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES);
2143: }
2144: PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0);
2145: return 0;
2146: }
2148: /*@
2149: MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2150: the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2151: using a local (per-processor) numbering.
2153: Not Collective
2155: Input Parameters:
2156: + x - the matrix
2157: . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2158: - cmapping - column mapping
2160: Level: intermediate
2162: Note:
2163: If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2165: .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2166: @*/
2167: PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2168: {
2173: if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2174: else {
2175: PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping);
2176: PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping);
2177: }
2178: return 0;
2179: }
2181: /*@
2182: MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2184: Not Collective
2186: Input Parameter:
2187: . A - the matrix
2189: Output Parameters:
2190: + rmapping - row mapping
2191: - cmapping - column mapping
2193: Level: advanced
2195: .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2196: @*/
2197: PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2198: {
2201: if (rmapping) {
2203: *rmapping = A->rmap->mapping;
2204: }
2205: if (cmapping) {
2207: *cmapping = A->cmap->mapping;
2208: }
2209: return 0;
2210: }
2212: /*@
2213: MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2215: Logically Collective on A
2217: Input Parameters:
2218: + A - the matrix
2219: . rmap - row layout
2220: - cmap - column layout
2222: Level: advanced
2224: Note:
2225: The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2227: .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2228: @*/
2229: PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2230: {
2232: PetscLayoutReference(rmap, &A->rmap);
2233: PetscLayoutReference(cmap, &A->cmap);
2234: return 0;
2235: }
2237: /*@
2238: MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2240: Not Collective
2242: Input Parameter:
2243: . A - the matrix
2245: Output Parameters:
2246: + rmap - row layout
2247: - cmap - column layout
2249: Level: advanced
2251: .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2252: @*/
2253: PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2254: {
2257: if (rmap) {
2259: *rmap = A->rmap;
2260: }
2261: if (cmap) {
2263: *cmap = A->cmap;
2264: }
2265: return 0;
2266: }
2268: /*@C
2269: MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2270: using a local numbering of the nodes.
2272: Not Collective
2274: Input Parameters:
2275: + mat - the matrix
2276: . nrow, irow - number of rows and their local indices
2277: . ncol, icol - number of columns and their local indices
2278: . y - a logically two-dimensional array of values
2279: - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2281: Notes:
2282: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2283: `MatSetUp()` before using this routine
2285: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2287: Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2288: options cannot be mixed without intervening calls to the assembly
2289: routines.
2291: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2292: MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2294: Level: intermediate
2296: Developer Note:
2297: This is labeled with C so does not automatically generate Fortran stubs and interfaces
2298: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2300: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2301: `MatGetValuesLocal()`
2302: @*/
2303: PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2304: {
2308: MatCheckPreallocated(mat, 1);
2309: if (!nrow || !ncol) return 0; /* no values to insert */
2312: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2314: if (PetscDefined(USE_DEBUG)) {
2317: }
2319: if (mat->assembled) {
2320: mat->was_assembled = PETSC_TRUE;
2321: mat->assembled = PETSC_FALSE;
2322: }
2323: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2324: if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2325: else {
2326: PetscInt buf[8192], *bufr = NULL, *bufc = NULL;
2327: const PetscInt *irowm, *icolm;
2329: if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2330: bufr = buf;
2331: bufc = buf + nrow;
2332: irowm = bufr;
2333: icolm = bufc;
2334: } else {
2335: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2336: irowm = bufr;
2337: icolm = bufc;
2338: }
2339: if (mat->rmap->mapping) ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr);
2340: else irowm = irow;
2341: if (mat->cmap->mapping) {
2342: if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2343: ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc);
2344: } else icolm = irowm;
2345: } else icolm = icol;
2346: MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv);
2347: if (bufr != buf) PetscFree2(bufr, bufc);
2348: }
2349: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2350: return 0;
2351: }
2353: /*@C
2354: MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2355: using a local ordering of the nodes a block at a time.
2357: Not Collective
2359: Input Parameters:
2360: + x - the matrix
2361: . nrow, irow - number of rows and their local indices
2362: . ncol, icol - number of columns and their local indices
2363: . y - a logically two-dimensional array of values
2364: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2366: Notes:
2367: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2368: `MatSetUp()` before using this routine
2370: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2371: before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2373: Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2374: options cannot be mixed without intervening calls to the assembly
2375: routines.
2377: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2378: MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2380: Level: intermediate
2382: Developer Note:
2383: This is labeled with C so does not automatically generate Fortran stubs and interfaces
2384: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2386: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2387: `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2388: @*/
2389: PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2390: {
2394: MatCheckPreallocated(mat, 1);
2395: if (!nrow || !ncol) return 0; /* no values to insert */
2398: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2400: if (PetscDefined(USE_DEBUG)) {
2403: }
2405: if (mat->assembled) {
2406: mat->was_assembled = PETSC_TRUE;
2407: mat->assembled = PETSC_FALSE;
2408: }
2409: if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2410: PetscInt irbs, rbs;
2411: MatGetBlockSizes(mat, &rbs, NULL);
2412: ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs);
2414: }
2415: if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2416: PetscInt icbs, cbs;
2417: MatGetBlockSizes(mat, NULL, &cbs);
2418: ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs);
2420: }
2421: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2422: if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2423: else {
2424: PetscInt buf[8192], *bufr = NULL, *bufc = NULL;
2425: const PetscInt *irowm, *icolm;
2427: if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2428: bufr = buf;
2429: bufc = buf + nrow;
2430: irowm = bufr;
2431: icolm = bufc;
2432: } else {
2433: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2434: irowm = bufr;
2435: icolm = bufc;
2436: }
2437: if (mat->rmap->mapping) ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr);
2438: else irowm = irow;
2439: if (mat->cmap->mapping) {
2440: if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2441: ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc);
2442: } else icolm = irowm;
2443: } else icolm = icol;
2444: MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv);
2445: if (bufr != buf) PetscFree2(bufr, bufc);
2446: }
2447: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2448: return 0;
2449: }
2451: /*@
2452: MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2454: Collective
2456: Input Parameters:
2457: + mat - the matrix
2458: - x - the vector to be multiplied
2460: Output Parameters:
2461: . y - the result
2463: Note:
2464: The vectors x and y cannot be the same. I.e., one cannot
2465: call `MatMultDiagonalBlock`(A,y,y).
2467: Level: developer
2469: .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2470: @*/
2471: PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2472: {
2481: MatCheckPreallocated(mat, 1);
2483: PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2484: PetscObjectStateIncrease((PetscObject)y);
2485: return 0;
2486: }
2488: /* --------------------------------------------------------*/
2489: /*@
2490: MatMult - Computes the matrix-vector product, y = Ax.
2492: Neighbor-wise Collective
2494: Input Parameters:
2495: + mat - the matrix
2496: - x - the vector to be multiplied
2498: Output Parameters:
2499: . y - the result
2501: Note:
2502: The vectors x and y cannot be the same. I.e., one cannot
2503: call `MatMult`(A,y,y).
2505: Level: beginner
2507: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2508: @*/
2509: PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2510: {
2522: VecSetErrorIfLocked(y, 3);
2523: if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2524: MatCheckPreallocated(mat, 1);
2526: VecLockReadPush(x);
2527: PetscLogEventBegin(MAT_Mult, mat, x, y, 0);
2528: PetscUseTypeMethod(mat, mult, x, y);
2529: PetscLogEventEnd(MAT_Mult, mat, x, y, 0);
2530: if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2531: VecLockReadPop(x);
2532: return 0;
2533: }
2535: /*@
2536: MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2538: Neighbor-wise Collective
2540: Input Parameters:
2541: + mat - the matrix
2542: - x - the vector to be multiplied
2544: Output Parameters:
2545: . y - the result
2547: Notes:
2548: The vectors x and y cannot be the same. I.e., one cannot
2549: call `MatMultTranspose`(A,y,y).
2551: For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2552: use `MatMultHermitianTranspose()`
2554: Level: beginner
2556: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2557: @*/
2558: PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2559: {
2560: PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2574: if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2575: MatCheckPreallocated(mat, 1);
2577: if (!mat->ops->multtranspose) {
2578: if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2580: } else op = mat->ops->multtranspose;
2581: PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0);
2582: VecLockReadPush(x);
2583: (*op)(mat, x, y);
2584: VecLockReadPop(x);
2585: PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0);
2586: PetscObjectStateIncrease((PetscObject)y);
2587: if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2588: return 0;
2589: }
2591: /*@
2592: MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2594: Neighbor-wise Collective
2596: Input Parameters:
2597: + mat - the matrix
2598: - x - the vector to be multilplied
2600: Output Parameters:
2601: . y - the result
2603: Notes:
2604: The vectors x and y cannot be the same. I.e., one cannot
2605: call `MatMultHermitianTranspose`(A,y,y).
2607: Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2609: For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2611: Level: beginner
2613: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2614: @*/
2615: PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2616: {
2629: MatCheckPreallocated(mat, 1);
2631: PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0);
2632: #if defined(PETSC_USE_COMPLEX)
2633: if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2634: VecLockReadPush(x);
2635: if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2636: else PetscUseTypeMethod(mat, mult, x, y);
2637: VecLockReadPop(x);
2638: } else {
2639: Vec w;
2640: VecDuplicate(x, &w);
2641: VecCopy(x, w);
2642: VecConjugate(w);
2643: MatMultTranspose(mat, w, y);
2644: VecDestroy(&w);
2645: VecConjugate(y);
2646: }
2647: PetscObjectStateIncrease((PetscObject)y);
2648: #else
2649: MatMultTranspose(mat, x, y);
2650: #endif
2651: PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0);
2652: return 0;
2653: }
2655: /*@
2656: MatMultAdd - Computes v3 = v2 + A * v1.
2658: Neighbor-wise Collective
2660: Input Parameters:
2661: + mat - the matrix
2662: - v1, v2 - the vectors
2664: Output Parameters:
2665: . v3 - the result
2667: Note:
2668: The vectors v1 and v3 cannot be the same. I.e., one cannot
2669: call `MatMultAdd`(A,v1,v2,v1).
2671: Level: beginner
2673: .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2674: @*/
2675: PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2676: {
2691: MatCheckPreallocated(mat, 1);
2693: PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3);
2694: VecLockReadPush(v1);
2695: PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2696: VecLockReadPop(v1);
2697: PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3);
2698: PetscObjectStateIncrease((PetscObject)v3);
2699: return 0;
2700: }
2702: /*@
2703: MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2705: Neighbor-wise Collective
2707: Input Parameters:
2708: + mat - the matrix
2709: - v1, v2 - the vectors
2711: Output Parameters:
2712: . v3 - the result
2714: Note:
2715: The vectors v1 and v3 cannot be the same. I.e., one cannot
2716: call `MatMultTransposeAdd`(A,v1,v2,v1).
2718: Level: beginner
2720: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2721: @*/
2722: PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2723: {
2724: PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2739: MatCheckPreallocated(mat, 1);
2741: PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3);
2742: VecLockReadPush(v1);
2743: (*op)(mat, v1, v2, v3);
2744: VecLockReadPop(v1);
2745: PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3);
2746: PetscObjectStateIncrease((PetscObject)v3);
2747: return 0;
2748: }
2750: /*@
2751: MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2753: Neighbor-wise Collective
2755: Input Parameters:
2756: + mat - the matrix
2757: - v1, v2 - the vectors
2759: Output Parameters:
2760: . v3 - the result
2762: Note:
2763: The vectors v1 and v3 cannot be the same. I.e., one cannot
2764: call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2766: Level: beginner
2768: .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2769: @*/
2770: PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2771: {
2784: MatCheckPreallocated(mat, 1);
2786: PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2787: VecLockReadPush(v1);
2788: if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2789: else {
2790: Vec w, z;
2791: VecDuplicate(v1, &w);
2792: VecCopy(v1, w);
2793: VecConjugate(w);
2794: VecDuplicate(v3, &z);
2795: MatMultTranspose(mat, w, z);
2796: VecDestroy(&w);
2797: VecConjugate(z);
2798: if (v2 != v3) {
2799: VecWAXPY(v3, 1.0, v2, z);
2800: } else {
2801: VecAXPY(v3, 1.0, z);
2802: }
2803: VecDestroy(&z);
2804: }
2805: VecLockReadPop(v1);
2806: PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2807: PetscObjectStateIncrease((PetscObject)v3);
2808: return 0;
2809: }
2811: /*@C
2812: MatGetFactorType - gets the type of factorization it is
2814: Not Collective
2816: Input Parameters:
2817: . mat - the matrix
2819: Output Parameters:
2820: . 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`
2822: Level: intermediate
2824: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2825: `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2826: @*/
2827: PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2828: {
2832: *t = mat->factortype;
2833: return 0;
2834: }
2836: /*@C
2837: MatSetFactorType - sets the type of factorization it is
2839: Logically Collective
2841: Input Parameters:
2842: + mat - the matrix
2843: - 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`
2845: Level: intermediate
2847: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2848: `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2849: @*/
2850: PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2851: {
2854: mat->factortype = t;
2855: return 0;
2856: }
2858: /* ------------------------------------------------------------*/
2859: /*@C
2860: MatGetInfo - Returns information about matrix storage (number of
2861: nonzeros, memory, etc.).
2863: Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2865: Input Parameter:
2866: . mat - the matrix
2868: Output Parameters:
2869: + flag - flag indicating the type of parameters to be returned
2870: (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors,
2871: MAT_GLOBAL_SUM - sum over all processors)
2872: - info - matrix information context
2874: Notes:
2875: The `MatInfo` context contains a variety of matrix data, including
2876: number of nonzeros allocated and used, number of mallocs during
2877: matrix assembly, etc. Additional information for factored matrices
2878: is provided (such as the fill ratio, number of mallocs during
2879: factorization, etc.). Much of this info is printed to `PETSC_STDOUT`
2880: when using the runtime options
2881: $ -info -mat_view ::ascii_info
2883: Example for C/C++ Users:
2884: See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2885: data within the MatInfo context. For example,
2886: .vb
2887: MatInfo info;
2888: Mat A;
2889: double mal, nz_a, nz_u;
2891: MatGetInfo(A,MAT_LOCAL,&info);
2892: mal = info.mallocs;
2893: nz_a = info.nz_allocated;
2894: .ve
2896: Example for Fortran Users:
2897: Fortran users should declare info as a double precision
2898: array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2899: of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2900: a complete list of parameter names.
2901: .vb
2902: double precision info(MAT_INFO_SIZE)
2903: double precision mal, nz_a
2904: Mat A
2905: integer ierr
2907: call MatGetInfo(A,MAT_LOCAL,info,ierr)
2908: mal = info(MAT_INFO_MALLOCS)
2909: nz_a = info(MAT_INFO_NZ_ALLOCATED)
2910: .ve
2912: Level: intermediate
2914: Developer Note:
2915: Fortran interface is not autogenerated as the
2916: interface definition cannot be generated correctly [due to MatInfo]
2918: .seealso: `MatInfo`, `MatStashGetInfo()`
2919: @*/
2920: PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2921: {
2925: MatCheckPreallocated(mat, 1);
2926: PetscUseTypeMethod(mat, getinfo, flag, info);
2927: return 0;
2928: }
2930: /*
2931: This is used by external packages where it is not easy to get the info from the actual
2932: matrix factorization.
2933: */
2934: PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2935: {
2936: PetscMemzero(info, sizeof(MatInfo));
2937: return 0;
2938: }
2940: /* ----------------------------------------------------------*/
2942: /*@C
2943: MatLUFactor - Performs in-place LU factorization of matrix.
2945: Collective
2947: Input Parameters:
2948: + mat - the matrix
2949: . row - row permutation
2950: . col - column permutation
2951: - info - options for factorization, includes
2952: $ fill - expected fill as ratio of original fill.
2953: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2954: $ Run with the option -info to determine an optimal value to use
2956: Notes:
2957: Most users should employ the `KSP` interface for linear solvers
2958: instead of working directly with matrix algebra routines such as this.
2959: See, e.g., `KSPCreate()`.
2961: This changes the state of the matrix to a factored matrix; it cannot be used
2962: for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
2964: This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
2965: when not using `KSP`.
2967: Level: developer
2969: Developer Note:
2970: The Fortran interface is not autogenerated as the
2971: interface definition cannot be generated correctly [due to `MatFactorInfo`]
2973: .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2974: `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2975: @*/
2976: PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
2977: {
2978: MatFactorInfo tinfo;
2987: MatCheckPreallocated(mat, 1);
2988: if (!info) {
2989: MatFactorInfoInitialize(&tinfo);
2990: info = &tinfo;
2991: }
2993: PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0);
2994: PetscUseTypeMethod(mat, lufactor, row, col, info);
2995: PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0);
2996: PetscObjectStateIncrease((PetscObject)mat);
2997: return 0;
2998: }
3000: /*@C
3001: MatILUFactor - Performs in-place ILU factorization of matrix.
3003: Collective
3005: Input Parameters:
3006: + mat - the matrix
3007: . row - row permutation
3008: . col - column permutation
3009: - info - structure containing
3010: $ levels - number of levels of fill.
3011: $ expected fill - as ratio of original fill.
3012: $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3013: missing diagonal entries)
3015: Level: developer
3017: Notes:
3018: Most users should employ the `KSP` interface for linear solvers
3019: instead of working directly with matrix algebra routines such as this.
3020: See, e.g., `KSPCreate()`.
3022: Probably really in-place only when level of fill is zero, otherwise allocates
3023: new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3024: when not using `KSP`.
3026: Developer Note:
3027: The Fortran interface is not autogenerated as the
3028: interface definition cannot be generated correctly [due to MatFactorInfo]
3030: .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3031: @*/
3032: PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3033: {
3042: MatCheckPreallocated(mat, 1);
3044: PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0);
3045: PetscUseTypeMethod(mat, ilufactor, row, col, info);
3046: PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0);
3047: PetscObjectStateIncrease((PetscObject)mat);
3048: return 0;
3049: }
3051: /*@C
3052: MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3053: Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3055: Collective on fact
3057: Input Parameters:
3058: + fact - the factor matrix obtained with `MatGetFactor()`
3059: . mat - the matrix
3060: . row, col - row and column permutations
3061: - info - options for factorization, includes
3062: .vb
3063: fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3064: dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3065: .ve
3067: Level: developer
3069: Notes:
3070: See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3072: Most users should employ the simplified `KSP` interface for linear solvers
3073: instead of working directly with matrix algebra routines such as this.
3074: See, e.g., `KSPCreate()`.
3076: Developer Note:
3077: The Fortran interface is not autogenerated as the
3078: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3080: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3081: @*/
3082: PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3083: {
3084: MatFactorInfo tinfo;
3094: if (!(fact)->ops->lufactorsymbolic) {
3095: MatSolverType stype;
3096: MatFactorGetSolverType(fact, &stype);
3097: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3098: }
3099: MatCheckPreallocated(mat, 2);
3100: if (!info) {
3101: MatFactorInfoInitialize(&tinfo);
3102: info = &tinfo;
3103: }
3105: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0);
3106: (fact->ops->lufactorsymbolic)(fact, mat, row, col, info);
3107: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0);
3108: PetscObjectStateIncrease((PetscObject)fact);
3109: return 0;
3110: }
3112: /*@C
3113: MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3114: Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3116: Collective on fact
3118: Input Parameters:
3119: + fact - the factor matrix obtained with `MatGetFactor()`
3120: . mat - the matrix
3121: - info - options for factorization
3123: Level: developer
3125: Notes:
3126: See `MatLUFactor()` for in-place factorization. See
3127: `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3129: Most users should employ the `KSP` interface for linear solvers
3130: instead of working directly with matrix algebra routines such as this.
3131: See, e.g., `KSPCreate()`.
3133: Developer Note:
3134: The Fortran interface is not autogenerated as the
3135: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3137: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3138: @*/
3139: PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3140: {
3141: MatFactorInfo tinfo;
3149: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3152: MatCheckPreallocated(mat, 2);
3153: if (!info) {
3154: MatFactorInfoInitialize(&tinfo);
3155: info = &tinfo;
3156: }
3158: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0);
3159: else PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0);
3160: (fact->ops->lufactornumeric)(fact, mat, info);
3161: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0);
3162: else PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0);
3163: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3164: PetscObjectStateIncrease((PetscObject)fact);
3165: return 0;
3166: }
3168: /*@C
3169: MatCholeskyFactor - Performs in-place Cholesky factorization of a
3170: symmetric matrix.
3172: Collective
3174: Input Parameters:
3175: + mat - the matrix
3176: . perm - row and column permutations
3177: - f - expected fill as ratio of original fill
3179: Level: developer
3181: Notes:
3182: See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`,
3183: `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3185: Most users should employ the `KSP` interface for linear solvers
3186: instead of working directly with matrix algebra routines such as this.
3187: See, e.g., `KSPCreate()`.
3189: Developer Note:
3190: The Fortran interface is not autogenerated as the
3191: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3193: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3194: `MatGetOrdering()`
3195: @*/
3196: PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3197: {
3198: MatFactorInfo tinfo;
3207: MatCheckPreallocated(mat, 1);
3208: if (!info) {
3209: MatFactorInfoInitialize(&tinfo);
3210: info = &tinfo;
3211: }
3213: PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0);
3214: PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3215: PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0);
3216: PetscObjectStateIncrease((PetscObject)mat);
3217: return 0;
3218: }
3220: /*@C
3221: MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3222: of a symmetric matrix.
3224: Collective on fact
3226: Input Parameters:
3227: + fact - the factor matrix obtained with `MatGetFactor()`
3228: . mat - the matrix
3229: . perm - row and column permutations
3230: - info - options for factorization, includes
3231: .vb
3232: fill - expected fill as ratio of original fill.
3233: dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3234: Run with the option -info to determine an optimal value to use
3235: .ve
3237: Level: developer
3239: Notes:
3240: See `MatLUFactorSymbolic()` for the nonsymmetric case. See also
3241: `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3243: Most users should employ the `KSP` interface for linear solvers
3244: instead of working directly with matrix algebra routines such as this.
3245: See, e.g., `KSPCreate()`.
3247: Developer Note:
3248: The Fortran interface is not autogenerated as the
3249: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3251: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3252: `MatGetOrdering()`
3253: @*/
3254: PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3255: {
3256: MatFactorInfo tinfo;
3266: if (!(fact)->ops->choleskyfactorsymbolic) {
3267: MatSolverType stype;
3268: MatFactorGetSolverType(fact, &stype);
3269: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3270: }
3271: MatCheckPreallocated(mat, 2);
3272: if (!info) {
3273: MatFactorInfoInitialize(&tinfo);
3274: info = &tinfo;
3275: }
3277: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3278: (fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info);
3279: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3280: PetscObjectStateIncrease((PetscObject)fact);
3281: return 0;
3282: }
3284: /*@C
3285: MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3286: of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3287: `MatCholeskyFactorSymbolic()`.
3289: Collective on fact
3291: Input Parameters:
3292: + fact - the factor matrix obtained with `MatGetFactor()`
3293: . mat - the initial matrix
3294: . info - options for factorization
3295: - fact - the symbolic factor of mat
3297: Level: developer
3299: Note:
3300: Most users should employ the `KSP` interface for linear solvers
3301: instead of working directly with matrix algebra routines such as this.
3302: See, e.g., `KSPCreate()`.
3304: Developer Note:
3305: The Fortran interface is not autogenerated as the
3306: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3308: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3309: @*/
3310: PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3311: {
3312: MatFactorInfo tinfo;
3321: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3322: MatCheckPreallocated(mat, 2);
3323: if (!info) {
3324: MatFactorInfoInitialize(&tinfo);
3325: info = &tinfo;
3326: }
3328: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3329: else PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0);
3330: (fact->ops->choleskyfactornumeric)(fact, mat, info);
3331: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3332: else PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0);
3333: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3334: PetscObjectStateIncrease((PetscObject)fact);
3335: return 0;
3336: }
3338: /*@
3339: MatQRFactor - Performs in-place QR factorization of matrix.
3341: Collective
3343: Input Parameters:
3344: + mat - the matrix
3345: . col - column permutation
3346: - info - options for factorization, includes
3347: .vb
3348: fill - expected fill as ratio of original fill.
3349: dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3350: Run with the option -info to determine an optimal value to use
3351: .ve
3353: Level: developer
3355: Notes:
3356: Most users should employ the `KSP` interface for linear solvers
3357: instead of working directly with matrix algebra routines such as this.
3358: See, e.g., `KSPCreate()`.
3360: This changes the state of the matrix to a factored matrix; it cannot be used
3361: for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3363: Developer Note:
3364: The Fortran interface is not autogenerated as the
3365: interface definition cannot be generated correctly [due to MatFactorInfo]
3367: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3368: `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3369: @*/
3370: PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3371: {
3378: MatCheckPreallocated(mat, 1);
3379: PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0);
3380: PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3381: PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0);
3382: PetscObjectStateIncrease((PetscObject)mat);
3383: return 0;
3384: }
3386: /*@
3387: MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3388: Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3390: Collective on fact
3392: Input Parameters:
3393: + fact - the factor matrix obtained with `MatGetFactor()`
3394: . mat - the matrix
3395: . col - column permutation
3396: - info - options for factorization, includes
3397: .vb
3398: fill - expected fill as ratio of original fill.
3399: dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3400: Run with the option -info to determine an optimal value to use
3401: .ve
3403: Level: developer
3405: Note:
3406: Most users should employ the `KSP` interface for linear solvers
3407: instead of working directly with matrix algebra routines such as this.
3408: See, e.g., `KSPCreate()`.
3410: Developer Note:
3411: The Fortran interface is not autogenerated as the
3412: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3414: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3415: @*/
3416: PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3417: {
3418: MatFactorInfo tinfo;
3427: MatCheckPreallocated(mat, 2);
3428: if (!info) {
3429: MatFactorInfoInitialize(&tinfo);
3430: info = &tinfo;
3431: }
3433: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0);
3434: PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3435: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0);
3436: PetscObjectStateIncrease((PetscObject)fact);
3437: return 0;
3438: }
3440: /*@
3441: MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3442: Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3444: Collective on fact
3446: Input Parameters:
3447: + fact - the factor matrix obtained with `MatGetFactor()`
3448: . mat - the matrix
3449: - info - options for factorization
3451: Level: developer
3453: Notes:
3454: See `MatQRFactor()` for in-place factorization.
3456: Most users should employ the `KSP` interface for linear solvers
3457: instead of working directly with matrix algebra routines such as this.
3458: See, e.g., `KSPCreate()`.
3460: Developer Note:
3461: The Fortran interface is not autogenerated as the
3462: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3464: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3465: @*/
3466: PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3467: {
3468: MatFactorInfo tinfo;
3476: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3478: MatCheckPreallocated(mat, 2);
3479: if (!info) {
3480: MatFactorInfoInitialize(&tinfo);
3481: info = &tinfo;
3482: }
3484: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0);
3485: else PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0);
3486: PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3487: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0);
3488: else PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0);
3489: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3490: PetscObjectStateIncrease((PetscObject)fact);
3491: return 0;
3492: }
3494: /* ----------------------------------------------------------------*/
3495: /*@
3496: MatSolve - Solves A x = b, given a factored matrix.
3498: Neighbor-wise Collective
3500: Input Parameters:
3501: + mat - the factored matrix
3502: - b - the right-hand-side vector
3504: Output Parameter:
3505: . x - the result vector
3507: Notes:
3508: The vectors b and x cannot be the same. I.e., one cannot
3509: call `MatSolve`(A,x,x).
3511: Most users should employ the `KSP` interface for linear solvers
3512: instead of working directly with matrix algebra routines such as this.
3513: See, e.g., `KSPCreate()`.
3515: Level: developer
3517: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3518: @*/
3519: PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3520: {
3531: if (!mat->rmap->N && !mat->cmap->N) return 0;
3532: MatCheckPreallocated(mat, 1);
3534: PetscLogEventBegin(MAT_Solve, mat, b, x, 0);
3535: if (mat->factorerrortype) {
3536: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3537: VecSetInf(x);
3538: } else PetscUseTypeMethod(mat, solve, b, x);
3539: PetscLogEventEnd(MAT_Solve, mat, b, x, 0);
3540: PetscObjectStateIncrease((PetscObject)x);
3541: return 0;
3542: }
3544: static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3545: {
3546: Vec b, x;
3547: PetscInt N, i;
3548: PetscErrorCode (*f)(Mat, Vec, Vec);
3549: PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3551: if (A->factorerrortype) {
3552: PetscInfo(A, "MatFactorError %d\n", A->factorerrortype);
3553: MatSetInf(X);
3554: return 0;
3555: }
3556: f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3558: MatBoundToCPU(A, &Abound);
3559: if (!Abound) {
3560: PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "");
3561: PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "");
3562: }
3563: #if defined(PETSC_HAVE_CUDA)
3564: if (Bneedconv) MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B);
3565: if (Xneedconv) MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X);
3566: #elif (PETSC_HAVE_HIP)
3567: if (Bneedconv) MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B);
3568: if (Xneedconv) MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X);
3569: #endif
3570: MatGetSize(B, NULL, &N);
3571: for (i = 0; i < N; i++) {
3572: MatDenseGetColumnVecRead(B, i, &b);
3573: MatDenseGetColumnVecWrite(X, i, &x);
3574: (*f)(A, b, x);
3575: MatDenseRestoreColumnVecWrite(X, i, &x);
3576: MatDenseRestoreColumnVecRead(B, i, &b);
3577: }
3578: if (Bneedconv) MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B);
3579: if (Xneedconv) MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X);
3580: return 0;
3581: }
3583: /*@
3584: MatMatSolve - Solves A X = B, given a factored matrix.
3586: Neighbor-wise Collective on A
3588: Input Parameters:
3589: + A - the factored matrix
3590: - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3592: Output Parameter:
3593: . X - the result matrix (dense matrix)
3595: Note:
3596: If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO;
3597: otherwise, B and X cannot be the same.
3599: Level: developer
3601: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3602: @*/
3603: PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3604: {
3614: if (!A->rmap->N && !A->cmap->N) return 0;
3616: MatCheckPreallocated(A, 1);
3618: PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3619: if (!A->ops->matsolve) {
3620: PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name);
3621: MatMatSolve_Basic(A, B, X, PETSC_FALSE);
3622: } else PetscUseTypeMethod(A, matsolve, B, X);
3623: PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3624: PetscObjectStateIncrease((PetscObject)X);
3625: return 0;
3626: }
3628: /*@
3629: MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3631: Neighbor-wise Collective on A
3633: Input Parameters:
3634: + A - the factored matrix
3635: - B - the right-hand-side matrix (`MATDENSE` matrix)
3637: Output Parameter:
3638: . X - the result matrix (dense matrix)
3640: Note:
3641: The matrices B and X cannot be the same. I.e., one cannot
3642: call `MatMatSolveTranspose`(A,X,X).
3644: Level: developer
3646: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3647: @*/
3648: PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3649: {
3661: if (!A->rmap->N && !A->cmap->N) return 0;
3663: MatCheckPreallocated(A, 1);
3665: PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3666: if (!A->ops->matsolvetranspose) {
3667: PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name);
3668: MatMatSolve_Basic(A, B, X, PETSC_TRUE);
3669: } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3670: PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3671: PetscObjectStateIncrease((PetscObject)X);
3672: return 0;
3673: }
3675: /*@
3676: MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3678: Neighbor-wise Collective on A
3680: Input Parameters:
3681: + A - the factored matrix
3682: - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3684: Output Parameter:
3685: . X - the result matrix (dense matrix)
3687: Note:
3688: 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
3689: format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3691: Level: developer
3693: .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3694: @*/
3695: PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3696: {
3708: if (!A->rmap->N && !A->cmap->N) return 0;
3710: MatCheckPreallocated(A, 1);
3712: PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0);
3713: PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3714: PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0);
3715: PetscObjectStateIncrease((PetscObject)X);
3716: return 0;
3717: }
3719: /*@
3720: MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3721: U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3723: Neighbor-wise Collective
3725: Input Parameters:
3726: + mat - the factored matrix
3727: - b - the right-hand-side vector
3729: Output Parameter:
3730: . x - the result vector
3732: Notes:
3733: `MatSolve()` should be used for most applications, as it performs
3734: a forward solve followed by a backward solve.
3736: The vectors b and x cannot be the same, i.e., one cannot
3737: call `MatForwardSolve`(A,x,x).
3739: For matrix in `MATSEQBAIJ` format with block size larger than 1,
3740: the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3741: `MatForwardSolve()` solves U^T*D y = b, and
3742: `MatBackwardSolve()` solves U x = y.
3743: Thus they do not provide a symmetric preconditioner.
3745: Level: developer
3747: .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3748: @*/
3749: PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3750: {
3761: if (!mat->rmap->N && !mat->cmap->N) return 0;
3762: MatCheckPreallocated(mat, 1);
3764: PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0);
3765: PetscUseTypeMethod(mat, forwardsolve, b, x);
3766: PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0);
3767: PetscObjectStateIncrease((PetscObject)x);
3768: return 0;
3769: }
3771: /*@
3772: MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3773: D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3775: Neighbor-wise Collective
3777: Input Parameters:
3778: + mat - the factored matrix
3779: - b - the right-hand-side vector
3781: Output Parameter:
3782: . x - the result vector
3784: Notes:
3785: `MatSolve()` should be used for most applications, as it performs
3786: a forward solve followed by a backward solve.
3788: The vectors b and x cannot be the same. I.e., one cannot
3789: call `MatBackwardSolve`(A,x,x).
3791: For matrix in `MATSEQBAIJ` format with block size larger than 1,
3792: the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3793: `MatForwardSolve()` solves U^T*D y = b, and
3794: `MatBackwardSolve()` solves U x = y.
3795: Thus they do not provide a symmetric preconditioner.
3797: Level: developer
3799: .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3800: @*/
3801: PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3802: {
3813: if (!mat->rmap->N && !mat->cmap->N) return 0;
3814: MatCheckPreallocated(mat, 1);
3816: PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0);
3817: PetscUseTypeMethod(mat, backwardsolve, b, x);
3818: PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0);
3819: PetscObjectStateIncrease((PetscObject)x);
3820: return 0;
3821: }
3823: /*@
3824: MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3826: Neighbor-wise Collective
3828: Input Parameters:
3829: + mat - the factored matrix
3830: . b - the right-hand-side vector
3831: - y - the vector to be added to
3833: Output Parameter:
3834: . x - the result vector
3836: Note:
3837: The vectors b and x cannot be the same. I.e., one cannot
3838: call `MatSolveAdd`(A,x,y,x).
3840: Level: developer
3842: .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3843: @*/
3844: PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3845: {
3846: PetscScalar one = 1.0;
3847: Vec tmp;
3863: if (!mat->rmap->N && !mat->cmap->N) return 0;
3864: MatCheckPreallocated(mat, 1);
3866: PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y);
3867: if (mat->factorerrortype) {
3868: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3869: VecSetInf(x);
3870: } else if (mat->ops->solveadd) {
3871: PetscUseTypeMethod(mat, solveadd, b, y, x);
3872: } else {
3873: /* do the solve then the add manually */
3874: if (x != y) {
3875: MatSolve(mat, b, x);
3876: VecAXPY(x, one, y);
3877: } else {
3878: VecDuplicate(x, &tmp);
3879: VecCopy(x, tmp);
3880: MatSolve(mat, b, x);
3881: VecAXPY(x, one, tmp);
3882: VecDestroy(&tmp);
3883: }
3884: }
3885: PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y);
3886: PetscObjectStateIncrease((PetscObject)x);
3887: return 0;
3888: }
3890: /*@
3891: MatSolveTranspose - Solves A' x = b, given a factored matrix.
3893: Neighbor-wise Collective
3895: Input Parameters:
3896: + mat - the factored matrix
3897: - b - the right-hand-side vector
3899: Output Parameter:
3900: . x - the result vector
3902: Notes:
3903: The vectors b and x cannot be the same. I.e., one cannot
3904: call `MatSolveTranspose`(A,x,x).
3906: Most users should employ the `KSP` interface for linear solvers
3907: instead of working directly with matrix algebra routines such as this.
3908: See, e.g., `KSPCreate()`.
3910: Level: developer
3912: .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3913: @*/
3914: PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3915: {
3916: PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3927: if (!mat->rmap->N && !mat->cmap->N) return 0;
3928: MatCheckPreallocated(mat, 1);
3929: PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0);
3930: if (mat->factorerrortype) {
3931: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3932: VecSetInf(x);
3933: } else {
3935: (*f)(mat, b, x);
3936: }
3937: PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0);
3938: PetscObjectStateIncrease((PetscObject)x);
3939: return 0;
3940: }
3942: /*@
3943: MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3944: factored matrix.
3946: Neighbor-wise Collective
3948: Input Parameters:
3949: + mat - the factored matrix
3950: . b - the right-hand-side vector
3951: - y - the vector to be added to
3953: Output Parameter:
3954: . x - the result vector
3956: Note:
3957: The vectors b and x cannot be the same. I.e., one cannot
3958: call `MatSolveTransposeAdd`(A,x,y,x).
3960: Level: developer
3962: .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
3963: @*/
3964: PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
3965: {
3966: PetscScalar one = 1.0;
3967: Vec tmp;
3968: PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
3983: if (!mat->rmap->N && !mat->cmap->N) return 0;
3984: MatCheckPreallocated(mat, 1);
3986: PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y);
3987: if (mat->factorerrortype) {
3988: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3989: VecSetInf(x);
3990: } else if (f) {
3991: (*f)(mat, b, y, x);
3992: } else {
3993: /* do the solve then the add manually */
3994: if (x != y) {
3995: MatSolveTranspose(mat, b, x);
3996: VecAXPY(x, one, y);
3997: } else {
3998: VecDuplicate(x, &tmp);
3999: VecCopy(x, tmp);
4000: MatSolveTranspose(mat, b, x);
4001: VecAXPY(x, one, tmp);
4002: VecDestroy(&tmp);
4003: }
4004: }
4005: PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y);
4006: PetscObjectStateIncrease((PetscObject)x);
4007: return 0;
4008: }
4009: /* ----------------------------------------------------------------*/
4011: /*@
4012: MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4014: Neighbor-wise Collective
4016: Input Parameters:
4017: + mat - the matrix
4018: . b - the right hand side
4019: . omega - the relaxation factor
4020: . flag - flag indicating the type of SOR (see below)
4021: . shift - diagonal shift
4022: . its - the number of iterations
4023: - lits - the number of local iterations
4025: Output Parameter:
4026: . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4028: SOR Flags:
4029: + `SOR_FORWARD_SWEEP` - forward SOR
4030: . `SOR_BACKWARD_SWEEP` - backward SOR
4031: . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4032: . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4033: . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4034: . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4035: . `SOR_EISENSTAT` - SOR with Eisenstat trick
4036: . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4037: upper/lower triangular part of matrix to
4038: vector (with omega)
4039: - `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4041: Notes:
4042: `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4043: `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4044: on each processor.
4046: Application programmers will not generally use `MatSOR()` directly,
4047: but instead will employ the `KSP`/`PC` interface.
4049: For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4051: Most users should employ the `KSP` interface for linear solvers
4052: instead of working directly with matrix algebra routines such as this.
4053: See, e.g., `KSPCreate()`.
4055: Vectors x and b CANNOT be the same
4057: Notes for Advanced Users:
4058: The flags are implemented as bitwise inclusive or operations.
4059: For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4060: to specify a zero initial guess for SSOR.
4062: Developer Note:
4063: We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4065: Level: developer
4067: .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4068: @*/
4069: PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4070: {
4086: MatCheckPreallocated(mat, 1);
4087: PetscLogEventBegin(MAT_SOR, mat, b, x, 0);
4088: PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4089: PetscLogEventEnd(MAT_SOR, mat, b, x, 0);
4090: PetscObjectStateIncrease((PetscObject)x);
4091: return 0;
4092: }
4094: /*
4095: Default matrix copy routine.
4096: */
4097: PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4098: {
4099: PetscInt i, rstart = 0, rend = 0, nz;
4100: const PetscInt *cwork;
4101: const PetscScalar *vwork;
4103: if (B->assembled) MatZeroEntries(B);
4104: if (str == SAME_NONZERO_PATTERN) {
4105: MatGetOwnershipRange(A, &rstart, &rend);
4106: for (i = rstart; i < rend; i++) {
4107: MatGetRow(A, i, &nz, &cwork, &vwork);
4108: MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES);
4109: MatRestoreRow(A, i, &nz, &cwork, &vwork);
4110: }
4111: } else {
4112: MatAYPX(B, 0.0, A, str);
4113: }
4114: MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);
4115: MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);
4116: return 0;
4117: }
4119: /*@
4120: MatCopy - Copies a matrix to another matrix.
4122: Collective on A
4124: Input Parameters:
4125: + A - the matrix
4126: - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4128: Output Parameter:
4129: . B - where the copy is put
4131: Notes:
4132: If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4134: `MatCopy()` copies the matrix entries of a matrix to another existing
4135: matrix (after first zeroing the second matrix). A related routine is
4136: `MatConvert()`, which first creates a new matrix and then copies the data.
4138: Level: intermediate
4140: .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4141: @*/
4142: PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4143: {
4144: PetscInt i;
4151: MatCheckPreallocated(B, 2);
4155: A->cmap->N, B->cmap->N);
4156: MatCheckPreallocated(A, 1);
4157: if (A == B) return 0;
4159: PetscLogEventBegin(MAT_Copy, A, B, 0, 0);
4160: if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4161: else MatCopy_Basic(A, B, str);
4163: B->stencil.dim = A->stencil.dim;
4164: B->stencil.noc = A->stencil.noc;
4165: for (i = 0; i <= A->stencil.dim; i++) {
4166: B->stencil.dims[i] = A->stencil.dims[i];
4167: B->stencil.starts[i] = A->stencil.starts[i];
4168: }
4170: PetscLogEventEnd(MAT_Copy, A, B, 0, 0);
4171: PetscObjectStateIncrease((PetscObject)B);
4172: return 0;
4173: }
4175: /*@C
4176: MatConvert - Converts a matrix to another matrix, either of the same
4177: or different type.
4179: Collective
4181: Input Parameters:
4182: + mat - the matrix
4183: . newtype - new matrix type. Use `MATSAME` to create a new matrix of the
4184: same type as the original matrix.
4185: - reuse - denotes if the destination matrix is to be created or reused.
4186: 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
4187: `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).
4189: Output Parameter:
4190: . M - pointer to place new matrix
4192: Notes:
4193: `MatConvert()` first creates a new matrix and then copies the data from
4194: the first matrix. A related routine is `MatCopy()`, which copies the matrix
4195: entries of one matrix to another already existing matrix context.
4197: Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4198: the MPI communicator of the generated matrix is always the same as the communicator
4199: of the input matrix.
4201: Level: intermediate
4203: .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4204: @*/
4205: PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4206: {
4207: PetscBool sametype, issame, flg;
4208: PetscBool3 issymmetric, ishermitian;
4209: char convname[256], mtype[256];
4210: Mat B;
4217: MatCheckPreallocated(mat, 1);
4219: PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg);
4220: if (flg) newtype = mtype;
4222: PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype);
4223: PetscStrcmp(newtype, "same", &issame);
4227: if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4228: PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4229: return 0;
4230: }
4232: /* Cache Mat options because some converters use MatHeaderReplace */
4233: issymmetric = mat->symmetric;
4234: ishermitian = mat->hermitian;
4236: if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4237: PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4238: PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4239: } else {
4240: PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4241: const char *prefix[3] = {"seq", "mpi", ""};
4242: PetscInt i;
4243: /*
4244: Order of precedence:
4245: 0) See if newtype is a superclass of the current matrix.
4246: 1) See if a specialized converter is known to the current matrix.
4247: 2) See if a specialized converter is known to the desired matrix class.
4248: 3) See if a good general converter is registered for the desired class
4249: (as of 6/27/03 only MATMPIADJ falls into this category).
4250: 4) See if a good general converter is known for the current matrix.
4251: 5) Use a really basic converter.
4252: */
4254: /* 0) See if newtype is a superclass of the current matrix.
4255: i.e mat is mpiaij and newtype is aij */
4256: for (i = 0; i < 2; i++) {
4257: PetscStrncpy(convname, prefix[i], sizeof(convname));
4258: PetscStrlcat(convname, newtype, sizeof(convname));
4259: PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg);
4260: PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg);
4261: if (flg) {
4262: if (reuse == MAT_INPLACE_MATRIX) {
4263: PetscInfo(mat, "Early return\n");
4264: return 0;
4265: } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4266: PetscInfo(mat, "Calling MatDuplicate\n");
4267: PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4268: return 0;
4269: } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4270: PetscInfo(mat, "Calling MatCopy\n");
4271: MatCopy(mat, *M, SAME_NONZERO_PATTERN);
4272: return 0;
4273: }
4274: }
4275: }
4276: /* 1) See if a specialized converter is known to the current matrix and the desired class */
4277: for (i = 0; i < 3; i++) {
4278: PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4279: PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4280: PetscStrlcat(convname, "_", sizeof(convname));
4281: PetscStrlcat(convname, prefix[i], sizeof(convname));
4282: PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname));
4283: PetscStrlcat(convname, "_C", sizeof(convname));
4284: PetscObjectQueryFunction((PetscObject)mat, convname, &conv);
4285: PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv);
4286: if (conv) goto foundconv;
4287: }
4289: /* 2) See if a specialized converter is known to the desired matrix class. */
4290: MatCreate(PetscObjectComm((PetscObject)mat), &B);
4291: MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
4292: MatSetType(B, newtype);
4293: for (i = 0; i < 3; i++) {
4294: PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4295: PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4296: PetscStrlcat(convname, "_", sizeof(convname));
4297: PetscStrlcat(convname, prefix[i], sizeof(convname));
4298: PetscStrlcat(convname, newtype, sizeof(convname));
4299: PetscStrlcat(convname, "_C", sizeof(convname));
4300: PetscObjectQueryFunction((PetscObject)B, convname, &conv);
4301: PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv);
4302: if (conv) {
4303: MatDestroy(&B);
4304: goto foundconv;
4305: }
4306: }
4308: /* 3) See if a good general converter is registered for the desired class */
4309: conv = B->ops->convertfrom;
4310: PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv);
4311: MatDestroy(&B);
4312: if (conv) goto foundconv;
4314: /* 4) See if a good general converter is known for the current matrix */
4315: if (mat->ops->convert) conv = mat->ops->convert;
4316: PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv);
4317: if (conv) goto foundconv;
4319: /* 5) Use a really basic converter. */
4320: PetscInfo(mat, "Using MatConvert_Basic\n");
4321: conv = MatConvert_Basic;
4323: foundconv:
4324: PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4325: (*conv)(mat, newtype, reuse, M);
4326: if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4327: /* the block sizes must be same if the mappings are copied over */
4328: (*M)->rmap->bs = mat->rmap->bs;
4329: (*M)->cmap->bs = mat->cmap->bs;
4330: PetscObjectReference((PetscObject)mat->rmap->mapping);
4331: PetscObjectReference((PetscObject)mat->cmap->mapping);
4332: (*M)->rmap->mapping = mat->rmap->mapping;
4333: (*M)->cmap->mapping = mat->cmap->mapping;
4334: }
4335: (*M)->stencil.dim = mat->stencil.dim;
4336: (*M)->stencil.noc = mat->stencil.noc;
4337: for (i = 0; i <= mat->stencil.dim; i++) {
4338: (*M)->stencil.dims[i] = mat->stencil.dims[i];
4339: (*M)->stencil.starts[i] = mat->stencil.starts[i];
4340: }
4341: PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4342: }
4343: PetscObjectStateIncrease((PetscObject)*M);
4345: /* Copy Mat options */
4346: if (issymmetric == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE);
4347: else if (issymmetric == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE);
4348: if (ishermitian == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE);
4349: else if (ishermitian == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE);
4350: return 0;
4351: }
4353: /*@C
4354: MatFactorGetSolverType - Returns name of the package providing the factorization routines
4356: Not Collective
4358: Input Parameter:
4359: . mat - the matrix, must be a factored matrix
4361: Output Parameter:
4362: . type - the string name of the package (do not free this string)
4364: Level: intermediate
4366: Note:
4367: In Fortran you pass in a empty string and the package name will be copied into it.
4368: (Make sure the string is long enough)
4370: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4371: @*/
4372: PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4373: {
4374: PetscErrorCode (*conv)(Mat, MatSolverType *);
4380: PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv);
4381: if (conv) (*conv)(mat, type);
4382: else *type = MATSOLVERPETSC;
4383: return 0;
4384: }
4386: typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4387: struct _MatSolverTypeForSpecifcType {
4388: MatType mtype;
4389: /* no entry for MAT_FACTOR_NONE */
4390: PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4391: MatSolverTypeForSpecifcType next;
4392: };
4394: typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4395: struct _MatSolverTypeHolder {
4396: char *name;
4397: MatSolverTypeForSpecifcType handlers;
4398: MatSolverTypeHolder next;
4399: };
4401: static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4403: /*@C
4404: MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4406: Input Parameters:
4407: + package - name of the package, for example petsc or superlu
4408: . mtype - the matrix type that works with this package
4409: . ftype - the type of factorization supported by the package
4410: - createfactor - routine that will create the factored matrix ready to be used
4412: Level: developer
4414: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4415: @*/
4416: PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4417: {
4418: MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL;
4419: PetscBool flg;
4420: MatSolverTypeForSpecifcType inext, iprev = NULL;
4422: MatInitializePackage();
4423: if (!next) {
4424: PetscNew(&MatSolverTypeHolders);
4425: PetscStrallocpy(package, &MatSolverTypeHolders->name);
4426: PetscNew(&MatSolverTypeHolders->handlers);
4427: PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype);
4428: MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4429: return 0;
4430: }
4431: while (next) {
4432: PetscStrcasecmp(package, next->name, &flg);
4433: if (flg) {
4435: inext = next->handlers;
4436: while (inext) {
4437: PetscStrcasecmp(mtype, inext->mtype, &flg);
4438: if (flg) {
4439: inext->createfactor[(int)ftype - 1] = createfactor;
4440: return 0;
4441: }
4442: iprev = inext;
4443: inext = inext->next;
4444: }
4445: PetscNew(&iprev->next);
4446: PetscStrallocpy(mtype, (char **)&iprev->next->mtype);
4447: iprev->next->createfactor[(int)ftype - 1] = createfactor;
4448: return 0;
4449: }
4450: prev = next;
4451: next = next->next;
4452: }
4453: PetscNew(&prev->next);
4454: PetscStrallocpy(package, &prev->next->name);
4455: PetscNew(&prev->next->handlers);
4456: PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype);
4457: prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4458: return 0;
4459: }
4461: /*@C
4462: MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4464: Input Parameters:
4465: + type - name of the package, for example petsc or superlu
4466: . ftype - the type of factorization supported by the type
4467: - mtype - the matrix type that works with this type
4469: Output Parameters:
4470: + foundtype - `PETSC_TRUE` if the type was registered
4471: . foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4472: - createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4474: Level: developer
4476: .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4477: @*/
4478: PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4479: {
4480: MatSolverTypeHolder next = MatSolverTypeHolders;
4481: PetscBool flg;
4482: MatSolverTypeForSpecifcType inext;
4484: if (foundtype) *foundtype = PETSC_FALSE;
4485: if (foundmtype) *foundmtype = PETSC_FALSE;
4486: if (createfactor) *createfactor = NULL;
4488: if (type) {
4489: while (next) {
4490: PetscStrcasecmp(type, next->name, &flg);
4491: if (flg) {
4492: if (foundtype) *foundtype = PETSC_TRUE;
4493: inext = next->handlers;
4494: while (inext) {
4495: PetscStrbeginswith(mtype, inext->mtype, &flg);
4496: if (flg) {
4497: if (foundmtype) *foundmtype = PETSC_TRUE;
4498: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4499: return 0;
4500: }
4501: inext = inext->next;
4502: }
4503: }
4504: next = next->next;
4505: }
4506: } else {
4507: while (next) {
4508: inext = next->handlers;
4509: while (inext) {
4510: PetscStrcmp(mtype, inext->mtype, &flg);
4511: if (flg && inext->createfactor[(int)ftype - 1]) {
4512: if (foundtype) *foundtype = PETSC_TRUE;
4513: if (foundmtype) *foundmtype = PETSC_TRUE;
4514: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4515: return 0;
4516: }
4517: inext = inext->next;
4518: }
4519: next = next->next;
4520: }
4521: /* try with base classes inext->mtype */
4522: next = MatSolverTypeHolders;
4523: while (next) {
4524: inext = next->handlers;
4525: while (inext) {
4526: PetscStrbeginswith(mtype, inext->mtype, &flg);
4527: if (flg && inext->createfactor[(int)ftype - 1]) {
4528: if (foundtype) *foundtype = PETSC_TRUE;
4529: if (foundmtype) *foundmtype = PETSC_TRUE;
4530: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4531: return 0;
4532: }
4533: inext = inext->next;
4534: }
4535: next = next->next;
4536: }
4537: }
4538: return 0;
4539: }
4541: PetscErrorCode MatSolverTypeDestroy(void)
4542: {
4543: MatSolverTypeHolder next = MatSolverTypeHolders, prev;
4544: MatSolverTypeForSpecifcType inext, iprev;
4546: while (next) {
4547: PetscFree(next->name);
4548: inext = next->handlers;
4549: while (inext) {
4550: PetscFree(inext->mtype);
4551: iprev = inext;
4552: inext = inext->next;
4553: PetscFree(iprev);
4554: }
4555: prev = next;
4556: next = next->next;
4557: PetscFree(prev);
4558: }
4559: MatSolverTypeHolders = NULL;
4560: return 0;
4561: }
4563: /*@C
4564: MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4566: Logically Collective
4568: Input Parameters:
4569: . mat - the matrix
4571: Output Parameters:
4572: . flg - `PETSC_TRUE` if uses the ordering
4574: Note:
4575: Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4576: packages do not, thus we want to skip generating the ordering when it is not needed or used.
4578: Level: developer
4580: .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4581: @*/
4582: PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4583: {
4584: *flg = mat->canuseordering;
4585: return 0;
4586: }
4588: /*@C
4589: MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4591: Logically Collective
4593: Input Parameters:
4594: . mat - the matrix obtained with `MatGetFactor()`
4596: Output Parameters:
4597: . otype - the preferred type
4599: Level: developer
4601: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4602: @*/
4603: PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4604: {
4605: *otype = mat->preferredordering[ftype];
4607: return 0;
4608: }
4610: /*@C
4611: MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4613: Collective
4615: Input Parameters:
4616: + mat - the matrix
4617: . type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4618: - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4620: Output Parameters:
4621: . f - the factor matrix used with MatXXFactorSymbolic() calls
4623: Options Database Key:
4624: . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4625: One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4627: Notes:
4628: Users usually access the factorization solvers via `KSP`
4630: Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4631: such as pastix, superlu, mumps etc.
4633: PETSc must have been ./configure to use the external solver, using the option --download-package
4635: Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4636: where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4637: call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix.
4639: Developer Note:
4640: This should actually be called `MatCreateFactor()` since it creates a new factor object
4642: Level: intermediate
4644: .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4645: `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4646: @*/
4647: PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4648: {
4649: PetscBool foundtype, foundmtype;
4650: PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4656: MatCheckPreallocated(mat, 1);
4658: MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv);
4659: if (!foundtype) {
4660: if (type) {
4661: 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],
4662: ((PetscObject)mat)->type_name, type);
4663: } else {
4664: 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);
4665: }
4666: }
4670: (*conv)(mat, ftype, f);
4671: if (mat->factorprefix) MatSetOptionsPrefix(*f, mat->factorprefix);
4672: return 0;
4673: }
4675: /*@C
4676: MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4678: Not Collective
4680: Input Parameters:
4681: + mat - the matrix
4682: . type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4683: - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4685: Output Parameter:
4686: . flg - PETSC_TRUE if the factorization is available
4688: Notes:
4689: Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4690: such as pastix, superlu, mumps etc.
4692: PETSc must have been ./configure to use the external solver, using the option --download-package
4694: Developer Note:
4695: This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4697: Level: intermediate
4699: .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4700: `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4701: @*/
4702: PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4703: {
4704: PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4711: MatCheckPreallocated(mat, 1);
4713: MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv);
4714: *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4715: return 0;
4716: }
4718: /*@
4719: MatDuplicate - Duplicates a matrix including the non-zero structure.
4721: Collective
4723: Input Parameters:
4724: + mat - the matrix
4725: - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4726: See the manual page for `MatDuplicateOption()` for an explanation of these options.
4728: Output Parameter:
4729: . M - pointer to place new matrix
4731: Level: intermediate
4733: Notes:
4734: You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4736: 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.
4738: 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
4739: is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4740: User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4742: .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4743: @*/
4744: PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4745: {
4746: Mat B;
4747: VecType vtype;
4748: PetscInt i;
4749: PetscObject dm;
4750: void (*viewf)(void);
4757: MatCheckPreallocated(mat, 1);
4759: *M = NULL;
4760: PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4761: PetscUseTypeMethod(mat, duplicate, op, M);
4762: PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4763: B = *M;
4765: MatGetOperation(mat, MATOP_VIEW, &viewf);
4766: if (viewf) MatSetOperation(B, MATOP_VIEW, viewf);
4767: MatGetVecType(mat, &vtype);
4768: MatSetVecType(B, vtype);
4770: B->stencil.dim = mat->stencil.dim;
4771: B->stencil.noc = mat->stencil.noc;
4772: for (i = 0; i <= mat->stencil.dim; i++) {
4773: B->stencil.dims[i] = mat->stencil.dims[i];
4774: B->stencil.starts[i] = mat->stencil.starts[i];
4775: }
4777: B->nooffproczerorows = mat->nooffproczerorows;
4778: B->nooffprocentries = mat->nooffprocentries;
4780: PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm);
4781: if (dm) PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm);
4782: PetscObjectStateIncrease((PetscObject)B);
4783: return 0;
4784: }
4786: /*@
4787: MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4789: Logically Collective
4791: Input Parameters:
4792: + mat - the matrix
4793: - v - the vector for storing the diagonal
4795: Output Parameter:
4796: . v - the diagonal of the matrix
4798: Level: intermediate
4800: Note:
4801: Currently only correct in parallel for square matrices.
4803: .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4804: @*/
4805: PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4806: {
4811: MatCheckPreallocated(mat, 1);
4813: PetscUseTypeMethod(mat, getdiagonal, v);
4814: PetscObjectStateIncrease((PetscObject)v);
4815: return 0;
4816: }
4818: /*@C
4819: MatGetRowMin - Gets the minimum value (of the real part) of each
4820: row of the matrix
4822: Logically Collective
4824: Input Parameter:
4825: . mat - the matrix
4827: Output Parameters:
4828: + v - the vector for storing the maximums
4829: - idx - the indices of the column found for each row (optional)
4831: Level: intermediate
4833: Note:
4834: The result of this call are the same as if one converted the matrix to dense format
4835: and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4837: This code is only implemented for a couple of matrix formats.
4839: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4840: `MatGetRowMax()`
4841: @*/
4842: PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4843: {
4849: if (!mat->cmap->N) {
4850: VecSet(v, PETSC_MAX_REAL);
4851: if (idx) {
4852: PetscInt i, m = mat->rmap->n;
4853: for (i = 0; i < m; i++) idx[i] = -1;
4854: }
4855: } else {
4856: MatCheckPreallocated(mat, 1);
4857: }
4858: PetscUseTypeMethod(mat, getrowmin, v, idx);
4859: PetscObjectStateIncrease((PetscObject)v);
4860: return 0;
4861: }
4863: /*@C
4864: MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4865: row of the matrix
4867: Logically Collective
4869: Input Parameter:
4870: . mat - the matrix
4872: Output Parameters:
4873: + v - the vector for storing the minimums
4874: - idx - the indices of the column found for each row (or NULL if not needed)
4876: Level: intermediate
4878: Notes:
4879: if a row is completely empty or has only 0.0 values then the idx[] value for that
4880: row is 0 (the first column).
4882: This code is only implemented for a couple of matrix formats.
4884: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4885: @*/
4886: PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4887: {
4894: if (!mat->cmap->N) {
4895: VecSet(v, 0.0);
4896: if (idx) {
4897: PetscInt i, m = mat->rmap->n;
4898: for (i = 0; i < m; i++) idx[i] = -1;
4899: }
4900: } else {
4901: MatCheckPreallocated(mat, 1);
4902: if (idx) PetscArrayzero(idx, mat->rmap->n);
4903: PetscUseTypeMethod(mat, getrowminabs, v, idx);
4904: }
4905: PetscObjectStateIncrease((PetscObject)v);
4906: return 0;
4907: }
4909: /*@C
4910: MatGetRowMax - Gets the maximum value (of the real part) of each
4911: row of the matrix
4913: Logically Collective
4915: Input Parameter:
4916: . mat - the matrix
4918: Output Parameters:
4919: + v - the vector for storing the maximums
4920: - idx - the indices of the column found for each row (optional)
4922: Level: intermediate
4924: Notes:
4925: The result of this call are the same as if one converted the matrix to dense format
4926: and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4928: This code is only implemented for a couple of matrix formats.
4930: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4931: @*/
4932: PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
4933: {
4939: if (!mat->cmap->N) {
4940: VecSet(v, PETSC_MIN_REAL);
4941: if (idx) {
4942: PetscInt i, m = mat->rmap->n;
4943: for (i = 0; i < m; i++) idx[i] = -1;
4944: }
4945: } else {
4946: MatCheckPreallocated(mat, 1);
4947: PetscUseTypeMethod(mat, getrowmax, v, idx);
4948: }
4949: PetscObjectStateIncrease((PetscObject)v);
4950: return 0;
4951: }
4953: /*@C
4954: MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4955: row of the matrix
4957: Logically Collective
4959: Input Parameter:
4960: . mat - the matrix
4962: Output Parameters:
4963: + v - the vector for storing the maximums
4964: - idx - the indices of the column found for each row (or NULL if not needed)
4966: Level: intermediate
4968: Notes:
4969: if a row is completely empty or has only 0.0 values then the idx[] value for that
4970: row is 0 (the first column).
4972: This code is only implemented for a couple of matrix formats.
4974: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4975: @*/
4976: PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
4977: {
4983: if (!mat->cmap->N) {
4984: VecSet(v, 0.0);
4985: if (idx) {
4986: PetscInt i, m = mat->rmap->n;
4987: for (i = 0; i < m; i++) idx[i] = -1;
4988: }
4989: } else {
4990: MatCheckPreallocated(mat, 1);
4991: if (idx) PetscArrayzero(idx, mat->rmap->n);
4992: PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
4993: }
4994: PetscObjectStateIncrease((PetscObject)v);
4995: return 0;
4996: }
4998: /*@
4999: MatGetRowSum - Gets the sum of each row of the matrix
5001: Logically or Neighborhood Collective
5003: Input Parameters:
5004: . mat - the matrix
5006: Output Parameter:
5007: . v - the vector for storing the sum of rows
5009: Level: intermediate
5011: Notes:
5012: This code is slow since it is not currently specialized for different formats
5014: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5015: @*/
5016: PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5017: {
5018: Vec ones;
5024: MatCheckPreallocated(mat, 1);
5025: MatCreateVecs(mat, &ones, NULL);
5026: VecSet(ones, 1.);
5027: MatMult(mat, ones, v);
5028: VecDestroy(&ones);
5029: return 0;
5030: }
5032: /*@
5033: MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5034: when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5036: Collective
5038: Input Parameter:
5039: . mat - the matrix to provide the transpose
5041: Output Parameter:
5042: . 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
5044: Level: advanced
5046: Note:
5047: 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
5048: routine allows bypassing that call.
5050: .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5051: @*/
5052: PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5053: {
5054: PetscContainer rB = NULL;
5055: MatParentState *rb = NULL;
5057: PetscNew(&rb);
5058: rb->id = ((PetscObject)mat)->id;
5059: rb->state = 0;
5060: MatGetNonzeroState(mat, &rb->nonzerostate);
5061: PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB);
5062: PetscContainerSetPointer(rB, rb);
5063: PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault);
5064: PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB);
5065: PetscObjectDereference((PetscObject)rB);
5066: return 0;
5067: }
5069: /*@
5070: MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5072: Collective
5074: Input Parameters:
5075: + mat - the matrix to transpose
5076: - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5078: Output Parameter:
5079: . B - the transpose
5081: Notes:
5082: If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5084: `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
5085: transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5087: 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.
5089: Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5091: If mat is unchanged from the last call this function returns immediately without recomputing the result
5093: If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5095: Level: intermediate
5097: .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5098: `MatTransposeSymbolic()`
5099: @*/
5100: PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5101: {
5102: PetscContainer rB = NULL;
5103: MatParentState *rb = NULL;
5111: MatCheckPreallocated(mat, 1);
5112: if (reuse == MAT_REUSE_MATRIX) {
5113: PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5115: PetscContainerGetPointer(rB, (void **)&rb);
5117: if (rb->state == ((PetscObject)mat)->state) return 0;
5118: }
5120: PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0);
5121: if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5122: PetscUseTypeMethod(mat, transpose, reuse, B);
5123: PetscObjectStateIncrease((PetscObject)*B);
5124: }
5125: PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0);
5127: if (reuse == MAT_INITIAL_MATRIX) MatTransposeSetPrecursor(mat, *B);
5128: if (reuse != MAT_INPLACE_MATRIX) {
5129: PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5130: PetscContainerGetPointer(rB, (void **)&rb);
5131: rb->state = ((PetscObject)mat)->state;
5132: rb->nonzerostate = mat->nonzerostate;
5133: }
5134: return 0;
5135: }
5137: /*@
5138: MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5140: Collective on A
5142: Input Parameters:
5143: . A - the matrix to transpose
5145: Output Parameter:
5146: . 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
5147: numerical portion.
5149: Level: intermediate
5151: Note:
5152: This is not supported for many matrix types, use `MatTranspose()` in those cases
5154: .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5155: @*/
5156: PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5157: {
5163: PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0);
5164: (*A->ops->transposesymbolic)(A, B);
5165: PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0);
5167: MatTransposeSetPrecursor(A, *B);
5168: return 0;
5169: }
5171: PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5172: {
5173: PetscContainer rB;
5174: MatParentState *rb;
5180: PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB);
5182: PetscContainerGetPointer(rB, (void **)&rb);
5185: return 0;
5186: }
5188: /*@
5189: MatIsTranspose - Test whether a matrix is another one's transpose,
5190: or its own, in which case it tests symmetry.
5192: Collective on A
5194: Input Parameters:
5195: + A - the matrix to test
5196: - B - the matrix to test against, this can equal the first parameter
5198: Output Parameters:
5199: . flg - the result
5201: Notes:
5202: Only available for `MATAIJ` matrices.
5204: The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5205: test involves parallel copies of the block-offdiagonal parts of the matrix.
5207: Level: intermediate
5209: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5210: @*/
5211: PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5212: {
5213: PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5218: PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f);
5219: PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g);
5220: *flg = PETSC_FALSE;
5221: if (f && g) {
5223: (*f)(A, B, tol, flg);
5224: } else {
5225: MatType mattype;
5227: MatGetType(f ? B : A, &mattype);
5228: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5229: }
5230: return 0;
5231: }
5233: /*@
5234: MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5236: Collective
5238: Input Parameters:
5239: + mat - the matrix to transpose and complex conjugate
5240: - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5242: Output Parameter:
5243: . B - the Hermitian transpose
5245: Level: intermediate
5247: .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5248: @*/
5249: PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5250: {
5251: MatTranspose(mat, reuse, B);
5252: #if defined(PETSC_USE_COMPLEX)
5253: MatConjugate(*B);
5254: #endif
5255: return 0;
5256: }
5258: /*@
5259: MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5261: Collective on A
5263: Input Parameters:
5264: + A - the matrix to test
5265: - B - the matrix to test against, this can equal the first parameter
5267: Output Parameters:
5268: . flg - the result
5270: Notes:
5271: Only available for `MATAIJ` matrices.
5273: The sequential algorithm
5274: has a running time of the order of the number of nonzeros; the parallel
5275: test involves parallel copies of the block-offdiagonal parts of the matrix.
5277: Level: intermediate
5279: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5280: @*/
5281: PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5282: {
5283: PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5288: PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f);
5289: PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g);
5290: if (f && g) {
5292: (*f)(A, B, tol, flg);
5293: }
5294: return 0;
5295: }
5297: /*@
5298: MatPermute - Creates a new matrix with rows and columns permuted from the
5299: original.
5301: Collective
5303: Input Parameters:
5304: + mat - the matrix to permute
5305: . row - row permutation, each processor supplies only the permutation for its rows
5306: - col - column permutation, each processor supplies only the permutation for its columns
5308: Output Parameters:
5309: . B - the permuted matrix
5311: Level: advanced
5313: Note:
5314: The index sets map from row/col of permuted matrix to row/col of original matrix.
5315: The index sets should be on the same communicator as mat and have the same local sizes.
5317: Developer Note:
5318: If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5319: exploit the fact that row and col are permutations, consider implementing the
5320: more general `MatCreateSubMatrix()` instead.
5322: .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5323: @*/
5324: PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5325: {
5336: MatCheckPreallocated(mat, 1);
5338: if (mat->ops->permute) {
5339: PetscUseTypeMethod(mat, permute, row, col, B);
5340: PetscObjectStateIncrease((PetscObject)*B);
5341: } else {
5342: MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B);
5343: }
5344: return 0;
5345: }
5347: /*@
5348: MatEqual - Compares two matrices.
5350: Collective on A
5352: Input Parameters:
5353: + A - the first matrix
5354: - B - the second matrix
5356: Output Parameter:
5357: . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5359: Level: intermediate
5361: .seealso: `Mat`
5362: @*/
5363: PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5364: {
5371: MatCheckPreallocated(A, 1);
5372: MatCheckPreallocated(B, 2);
5376: B->cmap->N);
5377: if (A->ops->equal && A->ops->equal == B->ops->equal) {
5378: PetscUseTypeMethod(A, equal, B, flg);
5379: } else {
5380: MatMultEqual(A, B, 10, flg);
5381: }
5382: return 0;
5383: }
5385: /*@
5386: MatDiagonalScale - Scales a matrix on the left and right by diagonal
5387: matrices that are stored as vectors. Either of the two scaling
5388: matrices can be NULL.
5390: Collective
5392: Input Parameters:
5393: + mat - the matrix to be scaled
5394: . l - the left scaling vector (or NULL)
5395: - r - the right scaling vector (or NULL)
5397: Note:
5398: `MatDiagonalScale()` computes A = LAR, where
5399: L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5400: The L scales the rows of the matrix, the R scales the columns of the matrix.
5402: Level: intermediate
5404: .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5405: @*/
5406: PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5407: {
5410: if (l) {
5413: }
5414: if (r) {
5417: }
5420: MatCheckPreallocated(mat, 1);
5421: if (!l && !r) return 0;
5423: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5424: PetscUseTypeMethod(mat, diagonalscale, l, r);
5425: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5426: PetscObjectStateIncrease((PetscObject)mat);
5427: if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5428: return 0;
5429: }
5431: /*@
5432: MatScale - Scales all elements of a matrix by a given number.
5434: Logically Collective
5436: Input Parameters:
5437: + mat - the matrix to be scaled
5438: - a - the scaling value
5440: Output Parameter:
5441: . mat - the scaled matrix
5443: Level: intermediate
5445: .seealso: `Mat`, `MatDiagonalScale()`
5446: @*/
5447: PetscErrorCode MatScale(Mat mat, PetscScalar a)
5448: {
5455: MatCheckPreallocated(mat, 1);
5457: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5458: if (a != (PetscScalar)1.0) {
5459: PetscUseTypeMethod(mat, scale, a);
5460: PetscObjectStateIncrease((PetscObject)mat);
5461: }
5462: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5463: return 0;
5464: }
5466: /*@
5467: MatNorm - Calculates various norms of a matrix.
5469: Collective
5471: Input Parameters:
5472: + mat - the matrix
5473: - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5475: Output Parameter:
5476: . nrm - the resulting norm
5478: Level: intermediate
5480: .seealso: `Mat`
5481: @*/
5482: PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5483: {
5490: MatCheckPreallocated(mat, 1);
5492: PetscUseTypeMethod(mat, norm, type, nrm);
5493: return 0;
5494: }
5496: /*
5497: This variable is used to prevent counting of MatAssemblyBegin() that
5498: are called from within a MatAssemblyEnd().
5499: */
5500: static PetscInt MatAssemblyEnd_InUse = 0;
5501: /*@
5502: MatAssemblyBegin - Begins assembling the matrix. This routine should
5503: be called after completing all calls to `MatSetValues()`.
5505: Collective
5507: Input Parameters:
5508: + mat - the matrix
5509: - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5511: Notes:
5512: `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to
5513: use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5515: Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5516: in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5517: using the matrix.
5519: ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5520: 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
5521: a global collective operation requiring all processes that share the matrix.
5523: Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5524: out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5525: before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5527: Level: beginner
5529: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5530: @*/
5531: PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5532: {
5535: MatCheckPreallocated(mat, 1);
5537: if (mat->assembled) {
5538: mat->was_assembled = PETSC_TRUE;
5539: mat->assembled = PETSC_FALSE;
5540: }
5542: if (!MatAssemblyEnd_InUse) {
5543: PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0);
5544: PetscTryTypeMethod(mat, assemblybegin, type);
5545: PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0);
5546: } else PetscTryTypeMethod(mat, assemblybegin, type);
5547: return 0;
5548: }
5550: /*@
5551: MatAssembled - Indicates if a matrix has been assembled and is ready for
5552: use; for example, in matrix-vector product.
5554: Not Collective
5556: Input Parameter:
5557: . mat - the matrix
5559: Output Parameter:
5560: . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5562: Level: advanced
5564: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5565: @*/
5566: PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5567: {
5570: *assembled = mat->assembled;
5571: return 0;
5572: }
5574: /*@
5575: MatAssemblyEnd - Completes assembling the matrix. This routine should
5576: be called after `MatAssemblyBegin()`.
5578: Collective on Mat
5580: Input Parameters:
5581: + mat - the matrix
5582: - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5584: Options Database Keys:
5585: + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5586: . -mat_view ::ascii_info_detail - Prints more detailed info
5587: . -mat_view - Prints matrix in ASCII format
5588: . -mat_view ::ascii_matlab - Prints matrix in Matlab format
5589: . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5590: . -display <name> - Sets display name (default is host)
5591: . -draw_pause <sec> - Sets number of seconds to pause after display
5592: . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5593: . -viewer_socket_machine <machine> - Machine to use for socket
5594: . -viewer_socket_port <port> - Port number to use for socket
5595: - -mat_view binary:filename[:append] - Save matrix to file in binary format
5597: Level: beginner
5599: .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5600: @*/
5601: PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5602: {
5603: static PetscInt inassm = 0;
5604: PetscBool flg = PETSC_FALSE;
5609: inassm++;
5610: MatAssemblyEnd_InUse++;
5611: if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5612: PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0);
5613: PetscTryTypeMethod(mat, assemblyend, type);
5614: PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0);
5615: } else PetscTryTypeMethod(mat, assemblyend, type);
5617: /* Flush assembly is not a true assembly */
5618: if (type != MAT_FLUSH_ASSEMBLY) {
5619: if (mat->num_ass) {
5620: if (!mat->symmetry_eternal) {
5621: mat->symmetric = PETSC_BOOL3_UNKNOWN;
5622: mat->hermitian = PETSC_BOOL3_UNKNOWN;
5623: }
5624: if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5625: if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5626: }
5627: mat->num_ass++;
5628: mat->assembled = PETSC_TRUE;
5629: mat->ass_nonzerostate = mat->nonzerostate;
5630: }
5632: mat->insertmode = NOT_SET_VALUES;
5633: MatAssemblyEnd_InUse--;
5634: PetscObjectStateIncrease((PetscObject)mat);
5635: if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5636: MatViewFromOptions(mat, NULL, "-mat_view");
5638: if (mat->checksymmetryonassembly) {
5639: MatIsSymmetric(mat, mat->checksymmetrytol, &flg);
5640: if (flg) {
5641: PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5642: } else {
5643: PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5644: }
5645: }
5646: if (mat->nullsp && mat->checknullspaceonassembly) MatNullSpaceTest(mat->nullsp, mat, NULL);
5647: }
5648: inassm--;
5649: return 0;
5650: }
5652: /*@
5653: MatSetOption - Sets a parameter option for a matrix. Some options
5654: may be specific to certain storage formats. Some options
5655: determine how values will be inserted (or added). Sorted,
5656: row-oriented input will generally assemble the fastest. The default
5657: is row-oriented.
5659: Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5661: Input Parameters:
5662: + mat - the matrix
5663: . option - the option, one of those listed below (and possibly others),
5664: - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5666: Options Describing Matrix Structure:
5667: + `MAT_SPD` - symmetric positive definite
5668: . `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5669: . `MAT_HERMITIAN` - transpose is the complex conjugation
5670: . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5671: . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5672: . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5673: - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5675: These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5676: do not need to be computed (usually at a high cost)
5678: Options For Use with `MatSetValues()`:
5679: Insert a logically dense subblock, which can be
5680: . `MAT_ROW_ORIENTED` - row-oriented (default)
5682: Note these options reflect the data you pass in with `MatSetValues()`; it has
5683: nothing to do with how the data is stored internally in the matrix
5684: data structure.
5686: When (re)assembling a matrix, we can restrict the input for
5687: efficiency/debugging purposes. These options include
5688: + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5689: . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5690: . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5691: . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5692: . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5693: . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5694: any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5695: performance for very large process counts.
5696: - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5697: of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5698: functions, instead sending only neighbor messages.
5700: Notes:
5701: Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5703: Some options are relevant only for particular matrix types and
5704: are thus ignored by others. Other options are not supported by
5705: certain matrix types and will generate an error message if set.
5707: If using Fortran to compute a matrix, one may need to
5708: use the column-oriented option (or convert to the row-oriented
5709: format).
5711: `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5712: that would generate a new entry in the nonzero structure is instead
5713: ignored. Thus, if memory has not alredy been allocated for this particular
5714: data, then the insertion is ignored. For dense matrices, in which
5715: the entire array is allocated, no entries are ever ignored.
5716: Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5718: `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5719: that would generate a new entry in the nonzero structure instead produces
5720: 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
5722: `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5723: that would generate a new entry that has not been preallocated will
5724: instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5725: only.) This is a useful flag when debugging matrix memory preallocation.
5726: If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5728: `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5729: other processors should be dropped, rather than stashed.
5730: This is useful if you know that the "owning" processor is also
5731: always generating the correct matrix entries, so that PETSc need
5732: not transfer duplicate entries generated on another processor.
5734: `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5735: searches during matrix assembly. When this flag is set, the hash table
5736: is created during the first matrix assembly. This hash table is
5737: used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5738: to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5739: should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5740: supported by` MATMPIBAIJ` format only.
5742: `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5743: are kept in the nonzero structure
5745: `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5746: a zero location in the matrix
5748: `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5750: `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5751: zero row routines and thus improves performance for very large process counts.
5753: `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5754: part of the matrix (since they should match the upper triangular part).
5756: `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5757: single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5758: with finite difference schemes with non-periodic boundary conditions.
5760: Developer Note:
5761: `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5762: places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5763: to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5764: not changed.
5766: Level: intermediate
5768: .seealso: `MatOption`, `Mat`, `MatGetOption()`
5769: @*/
5770: PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5771: {
5773: if (op > 0) {
5776: }
5780: switch (op) {
5781: case MAT_FORCE_DIAGONAL_ENTRIES:
5782: mat->force_diagonals = flg;
5783: return 0;
5784: case MAT_NO_OFF_PROC_ENTRIES:
5785: mat->nooffprocentries = flg;
5786: return 0;
5787: case MAT_SUBSET_OFF_PROC_ENTRIES:
5788: mat->assembly_subset = flg;
5789: if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5790: #if !defined(PETSC_HAVE_MPIUNI)
5791: MatStashScatterDestroy_BTS(&mat->stash);
5792: #endif
5793: mat->stash.first_assembly_done = PETSC_FALSE;
5794: }
5795: return 0;
5796: case MAT_NO_OFF_PROC_ZERO_ROWS:
5797: mat->nooffproczerorows = flg;
5798: return 0;
5799: case MAT_SPD:
5800: if (flg) {
5801: mat->spd = PETSC_BOOL3_TRUE;
5802: mat->symmetric = PETSC_BOOL3_TRUE;
5803: mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5804: } else {
5805: mat->spd = PETSC_BOOL3_FALSE;
5806: }
5807: break;
5808: case MAT_SYMMETRIC:
5809: mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5810: if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5811: #if !defined(PETSC_USE_COMPLEX)
5812: mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5813: #endif
5814: break;
5815: case MAT_HERMITIAN:
5816: mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5817: if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5818: #if !defined(PETSC_USE_COMPLEX)
5819: mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5820: #endif
5821: break;
5822: case MAT_STRUCTURALLY_SYMMETRIC:
5823: mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5824: break;
5825: case MAT_SYMMETRY_ETERNAL:
5827: mat->symmetry_eternal = flg;
5828: if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5829: break;
5830: case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5832: mat->structural_symmetry_eternal = flg;
5833: break;
5834: case MAT_SPD_ETERNAL:
5836: mat->spd_eternal = flg;
5837: if (flg) {
5838: mat->structural_symmetry_eternal = PETSC_TRUE;
5839: mat->symmetry_eternal = PETSC_TRUE;
5840: }
5841: break;
5842: case MAT_STRUCTURE_ONLY:
5843: mat->structure_only = flg;
5844: break;
5845: case MAT_SORTED_FULL:
5846: mat->sortedfull = flg;
5847: break;
5848: default:
5849: break;
5850: }
5851: PetscTryTypeMethod(mat, setoption, op, flg);
5852: return 0;
5853: }
5855: /*@
5856: MatGetOption - Gets a parameter option that has been set for a matrix.
5858: Logically Collective
5860: Input Parameters:
5861: + mat - the matrix
5862: - option - the option, this only responds to certain options, check the code for which ones
5864: Output Parameter:
5865: . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5867: Notes:
5868: Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5870: Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5871: `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5873: Level: intermediate
5875: .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5876: `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5877: @*/
5878: PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5879: {
5886: switch (op) {
5887: case MAT_NO_OFF_PROC_ENTRIES:
5888: *flg = mat->nooffprocentries;
5889: break;
5890: case MAT_NO_OFF_PROC_ZERO_ROWS:
5891: *flg = mat->nooffproczerorows;
5892: break;
5893: case MAT_SYMMETRIC:
5894: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5895: break;
5896: case MAT_HERMITIAN:
5897: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5898: break;
5899: case MAT_STRUCTURALLY_SYMMETRIC:
5900: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5901: break;
5902: case MAT_SPD:
5903: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
5904: break;
5905: case MAT_SYMMETRY_ETERNAL:
5906: *flg = mat->symmetry_eternal;
5907: break;
5908: case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5909: *flg = mat->symmetry_eternal;
5910: break;
5911: default:
5912: break;
5913: }
5914: return 0;
5915: }
5917: /*@
5918: MatZeroEntries - Zeros all entries of a matrix. For sparse matrices
5919: this routine retains the old nonzero structure.
5921: Logically Collective
5923: Input Parameters:
5924: . mat - the matrix
5926: Level: intermediate
5928: Note:
5929: 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.
5930: See the Performance chapter of the users manual for information on preallocating matrices.
5932: .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
5933: @*/
5934: PetscErrorCode MatZeroEntries(Mat mat)
5935: {
5940: MatCheckPreallocated(mat, 1);
5942: PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0);
5943: PetscUseTypeMethod(mat, zeroentries);
5944: PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0);
5945: PetscObjectStateIncrease((PetscObject)mat);
5946: return 0;
5947: }
5949: /*@
5950: MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5951: of a set of rows and columns of a matrix.
5953: Collective
5955: Input Parameters:
5956: + mat - the matrix
5957: . numRows - the number of rows to remove
5958: . rows - the global row indices
5959: . diag - value put in the diagonal of the eliminated rows
5960: . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5961: - b - optional vector of right hand side, that will be adjusted by provided solution
5963: Notes:
5964: This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5966: For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5967: 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
5969: If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5970: Krylov method to take advantage of the known solution on the zeroed rows.
5972: For the parallel case, all processes that share the matrix (i.e.,
5973: those in the communicator used for matrix creation) MUST call this
5974: routine, regardless of whether any rows being zeroed are owned by
5975: them.
5977: Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5979: Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5980: list only rows local to itself).
5982: The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
5984: Level: intermediate
5986: .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5987: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5988: @*/
5989: PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
5990: {
5996: MatCheckPreallocated(mat, 1);
5998: PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
5999: MatViewFromOptions(mat, NULL, "-mat_view");
6000: PetscObjectStateIncrease((PetscObject)mat);
6001: return 0;
6002: }
6004: /*@
6005: MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6006: of a set of rows and columns of a matrix.
6008: Collective
6010: Input Parameters:
6011: + mat - the matrix
6012: . is - the rows to zero
6013: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6014: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6015: - b - optional vector of right hand side, that will be adjusted by provided solution
6017: Note:
6018: See `MatZeroRowsColumns()` for details on how this routine operates.
6020: Level: intermediate
6022: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6023: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6024: @*/
6025: PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6026: {
6027: PetscInt numRows;
6028: const PetscInt *rows;
6034: ISGetLocalSize(is, &numRows);
6035: ISGetIndices(is, &rows);
6036: MatZeroRowsColumns(mat, numRows, rows, diag, x, b);
6037: ISRestoreIndices(is, &rows);
6038: return 0;
6039: }
6041: /*@
6042: MatZeroRows - Zeros all entries (except possibly the main diagonal)
6043: of a set of rows of a matrix.
6045: Collective
6047: Input Parameters:
6048: + mat - the matrix
6049: . numRows - the number of rows to remove
6050: . rows - the global row indices
6051: . diag - value put in the diagonal of the eliminated rows
6052: . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6053: - b - optional vector of right hand side, that will be adjusted by provided solution
6055: Notes:
6056: This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6058: For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6060: If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6061: Krylov method to take advantage of the known solution on the zeroed rows.
6063: 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)
6064: from the matrix.
6066: Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6067: 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
6068: formats this does not alter the nonzero structure.
6070: If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6071: of the matrix is not changed the values are
6072: merely zeroed.
6074: The user can set a value in the diagonal entry (or for the `MATAIJ` format
6075: formats can optionally remove the main diagonal entry from the
6076: nonzero structure as well, by passing 0.0 as the final argument).
6078: For the parallel case, all processes that share the matrix (i.e.,
6079: those in the communicator used for matrix creation) MUST call this
6080: routine, regardless of whether any rows being zeroed are owned by
6081: them.
6083: Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6084: list only rows local to itself).
6086: You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6087: owns that are to be zeroed. This saves a global synchronization in the implementation.
6089: Level: intermediate
6091: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6092: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6093: @*/
6094: PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6095: {
6101: MatCheckPreallocated(mat, 1);
6103: PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6104: MatViewFromOptions(mat, NULL, "-mat_view");
6105: PetscObjectStateIncrease((PetscObject)mat);
6106: return 0;
6107: }
6109: /*@
6110: MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6111: of a set of rows of a matrix.
6113: Collective on Mat
6115: Input Parameters:
6116: + mat - the matrix
6117: . is - index set of rows to remove (if NULL then no row is removed)
6118: . diag - value put in all diagonals of eliminated rows
6119: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6120: - b - optional vector of right hand side, that will be adjusted by provided solution
6122: Note:
6123: See `MatZeroRows()` for details on how this routine operates.
6125: Level: intermediate
6127: .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6128: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6129: @*/
6130: PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6131: {
6132: PetscInt numRows = 0;
6133: const PetscInt *rows = NULL;
6137: if (is) {
6139: ISGetLocalSize(is, &numRows);
6140: ISGetIndices(is, &rows);
6141: }
6142: MatZeroRows(mat, numRows, rows, diag, x, b);
6143: if (is) ISRestoreIndices(is, &rows);
6144: return 0;
6145: }
6147: /*@
6148: MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6149: of a set of rows of a matrix. These rows must be local to the process.
6151: Collective
6153: Input Parameters:
6154: + mat - the matrix
6155: . numRows - the number of rows to remove
6156: . rows - the grid coordinates (and component number when dof > 1) for matrix rows
6157: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6158: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6159: - b - optional vector of right hand side, that will be adjusted by provided solution
6161: Level: intermediate
6163: Notes:
6164: See `MatZeroRows()` for details on how this routine operates.
6166: The grid coordinates are across the entire grid, not just the local portion
6168: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6169: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6170: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6171: `DM_BOUNDARY_PERIODIC` boundary type.
6173: 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
6174: a single value per point) you can skip filling those indices.
6176: Fortran Note:
6177: idxm and idxn should be declared as
6178: $ MatStencil idxm(4,m)
6179: and the values inserted using
6180: .vb
6181: idxm(MatStencil_i,1) = i
6182: idxm(MatStencil_j,1) = j
6183: idxm(MatStencil_k,1) = k
6184: idxm(MatStencil_c,1) = c
6185: etc
6186: .ve
6188: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6189: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6190: @*/
6191: PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6192: {
6193: PetscInt dim = mat->stencil.dim;
6194: PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc);
6195: PetscInt *dims = mat->stencil.dims + 1;
6196: PetscInt *starts = mat->stencil.starts;
6197: PetscInt *dxm = (PetscInt *)rows;
6198: PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6204: PetscMalloc1(numRows, &jdxm);
6205: for (i = 0; i < numRows; ++i) {
6206: /* Skip unused dimensions (they are ordered k, j, i, c) */
6207: for (j = 0; j < 3 - sdim; ++j) dxm++;
6208: /* Local index in X dir */
6209: tmp = *dxm++ - starts[0];
6210: /* Loop over remaining dimensions */
6211: for (j = 0; j < dim - 1; ++j) {
6212: /* If nonlocal, set index to be negative */
6213: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6214: /* Update local index */
6215: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6216: }
6217: /* Skip component slot if necessary */
6218: if (mat->stencil.noc) dxm++;
6219: /* Local row number */
6220: if (tmp >= 0) jdxm[numNewRows++] = tmp;
6221: }
6222: MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b);
6223: PetscFree(jdxm);
6224: return 0;
6225: }
6227: /*@
6228: MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6229: of a set of rows and columns of a matrix.
6231: Collective
6233: Input Parameters:
6234: + mat - the matrix
6235: . numRows - the number of rows/columns to remove
6236: . rows - the grid coordinates (and component number when dof > 1) for matrix rows
6237: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6238: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6239: - b - optional vector of right hand side, that will be adjusted by provided solution
6241: Level: intermediate
6243: Notes:
6244: See `MatZeroRowsColumns()` for details on how this routine operates.
6246: The grid coordinates are across the entire grid, not just the local portion
6248: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6249: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6250: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6251: `DM_BOUNDARY_PERIODIC` boundary type.
6253: 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
6254: a single value per point) you can skip filling those indices.
6256: Fortran Note:
6257: In Fortran idxm and idxn should be declared as
6258: $ MatStencil idxm(4,m)
6259: and the values inserted using
6260: .vb
6261: idxm(MatStencil_i,1) = i
6262: idxm(MatStencil_j,1) = j
6263: idxm(MatStencil_k,1) = k
6264: idxm(MatStencil_c,1) = c
6265: etc
6266: .ve
6268: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6269: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6270: @*/
6271: PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6272: {
6273: PetscInt dim = mat->stencil.dim;
6274: PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc);
6275: PetscInt *dims = mat->stencil.dims + 1;
6276: PetscInt *starts = mat->stencil.starts;
6277: PetscInt *dxm = (PetscInt *)rows;
6278: PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6284: PetscMalloc1(numRows, &jdxm);
6285: for (i = 0; i < numRows; ++i) {
6286: /* Skip unused dimensions (they are ordered k, j, i, c) */
6287: for (j = 0; j < 3 - sdim; ++j) dxm++;
6288: /* Local index in X dir */
6289: tmp = *dxm++ - starts[0];
6290: /* Loop over remaining dimensions */
6291: for (j = 0; j < dim - 1; ++j) {
6292: /* If nonlocal, set index to be negative */
6293: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6294: /* Update local index */
6295: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6296: }
6297: /* Skip component slot if necessary */
6298: if (mat->stencil.noc) dxm++;
6299: /* Local row number */
6300: if (tmp >= 0) jdxm[numNewRows++] = tmp;
6301: }
6302: MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b);
6303: PetscFree(jdxm);
6304: return 0;
6305: }
6307: /*@C
6308: MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6309: of a set of rows of a matrix; using local numbering of rows.
6311: Collective
6313: Input Parameters:
6314: + mat - the matrix
6315: . numRows - the number of rows to remove
6316: . rows - the local row indices
6317: . diag - value put in all diagonals of eliminated rows
6318: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6319: - b - optional vector of right hand side, that will be adjusted by provided solution
6321: Notes:
6322: Before calling `MatZeroRowsLocal()`, the user must first set the
6323: local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6325: See `MatZeroRows()` for details on how this routine operates.
6327: Level: intermediate
6329: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6330: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6331: @*/
6332: PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6333: {
6339: MatCheckPreallocated(mat, 1);
6341: if (mat->ops->zerorowslocal) {
6342: PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6343: } else {
6344: IS is, newis;
6345: const PetscInt *newRows;
6348: ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6349: ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis);
6350: ISGetIndices(newis, &newRows);
6351: PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6352: ISRestoreIndices(newis, &newRows);
6353: ISDestroy(&newis);
6354: ISDestroy(&is);
6355: }
6356: PetscObjectStateIncrease((PetscObject)mat);
6357: return 0;
6358: }
6360: /*@
6361: MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6362: of a set of rows of a matrix; using local numbering of rows.
6364: Collective
6366: Input Parameters:
6367: + mat - the matrix
6368: . is - index set of rows to remove
6369: . diag - value put in all diagonals of eliminated rows
6370: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6371: - b - optional vector of right hand side, that will be adjusted by provided solution
6373: Notes:
6374: Before calling `MatZeroRowsLocalIS()`, the user must first set the
6375: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6377: See `MatZeroRows()` for details on how this routine operates.
6379: Level: intermediate
6381: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6382: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6383: @*/
6384: PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6385: {
6386: PetscInt numRows;
6387: const PetscInt *rows;
6394: MatCheckPreallocated(mat, 1);
6396: ISGetLocalSize(is, &numRows);
6397: ISGetIndices(is, &rows);
6398: MatZeroRowsLocal(mat, numRows, rows, diag, x, b);
6399: ISRestoreIndices(is, &rows);
6400: return 0;
6401: }
6403: /*@
6404: MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6405: of a set of rows and columns of a matrix; using local numbering of rows.
6407: Collective
6409: Input Parameters:
6410: + mat - the matrix
6411: . numRows - the number of rows to remove
6412: . rows - the global row indices
6413: . diag - value put in all diagonals of eliminated rows
6414: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6415: - b - optional vector of right hand side, that will be adjusted by provided solution
6417: Notes:
6418: Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6419: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6421: See `MatZeroRowsColumns()` for details on how this routine operates.
6423: Level: intermediate
6425: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6426: `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6427: @*/
6428: PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6429: {
6430: IS is, newis;
6431: const PetscInt *newRows;
6438: MatCheckPreallocated(mat, 1);
6441: ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6442: ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis);
6443: ISGetIndices(newis, &newRows);
6444: PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6445: ISRestoreIndices(newis, &newRows);
6446: ISDestroy(&newis);
6447: ISDestroy(&is);
6448: PetscObjectStateIncrease((PetscObject)mat);
6449: return 0;
6450: }
6452: /*@
6453: MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6454: of a set of rows and columns of a matrix; using local numbering of rows.
6456: Collective on Mat
6458: Input Parameters:
6459: + mat - the matrix
6460: . is - index set of rows to remove
6461: . diag - value put in all diagonals of eliminated rows
6462: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6463: - b - optional vector of right hand side, that will be adjusted by provided solution
6465: Notes:
6466: Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6467: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6469: See `MatZeroRowsColumns()` for details on how this routine operates.
6471: Level: intermediate
6473: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6474: `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6475: @*/
6476: PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6477: {
6478: PetscInt numRows;
6479: const PetscInt *rows;
6486: MatCheckPreallocated(mat, 1);
6488: ISGetLocalSize(is, &numRows);
6489: ISGetIndices(is, &rows);
6490: MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b);
6491: ISRestoreIndices(is, &rows);
6492: return 0;
6493: }
6495: /*@C
6496: MatGetSize - Returns the numbers of rows and columns in a matrix.
6498: Not Collective
6500: Input Parameter:
6501: . mat - the matrix
6503: Output Parameters:
6504: + m - the number of global rows
6505: - n - the number of global columns
6507: Note: both output parameters can be NULL on input.
6509: Level: beginner
6511: .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6512: @*/
6513: PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6514: {
6516: if (m) *m = mat->rmap->N;
6517: if (n) *n = mat->cmap->N;
6518: return 0;
6519: }
6521: /*@C
6522: MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6523: of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6525: Not Collective
6527: Input Parameter:
6528: . mat - the matrix
6530: Output Parameters:
6531: + m - the number of local rows, use `NULL` to not obtain this value
6532: - n - the number of local columns, use `NULL` to not obtain this value
6534: Level: beginner
6536: .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6537: @*/
6538: PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6539: {
6543: if (m) *m = mat->rmap->n;
6544: if (n) *n = mat->cmap->n;
6545: return 0;
6546: }
6548: /*@C
6549: MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6550: this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6552: Not Collective, unless matrix has not been allocated, then collective
6554: Input Parameter:
6555: . mat - the matrix
6557: Output Parameters:
6558: + m - the global index of the first local column, use `NULL` to not obtain this value
6559: - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6561: Level: developer
6563: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6564: @*/
6565: PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6566: {
6571: MatCheckPreallocated(mat, 1);
6572: if (m) *m = mat->cmap->rstart;
6573: if (n) *n = mat->cmap->rend;
6574: return 0;
6575: }
6577: /*@C
6578: MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6579: 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
6580: vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6582: Not Collective
6584: Input Parameter:
6585: . mat - the matrix
6587: Output Parameters:
6588: + m - the global index of the first local row, use `NULL` to not obtain this value
6589: - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6591: Note:
6592: This function requires that the matrix be preallocated. If you have not preallocated, consider using
6593: `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6594: and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6596: Level: beginner
6598: .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6599: `PetscLayout`
6600: @*/
6601: PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6602: {
6607: MatCheckPreallocated(mat, 1);
6608: if (m) *m = mat->rmap->rstart;
6609: if (n) *n = mat->rmap->rend;
6610: return 0;
6611: }
6613: /*@C
6614: MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6615: 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
6616: vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6618: Not Collective, unless matrix has not been allocated, then collective
6620: Input Parameters:
6621: . mat - the matrix
6623: Output Parameters:
6624: . ranges - start of each processors portion plus one more than the total length at the end
6626: Level: beginner
6628: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6629: @*/
6630: PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6631: {
6634: MatCheckPreallocated(mat, 1);
6635: PetscLayoutGetRanges(mat->rmap, ranges);
6636: return 0;
6637: }
6639: /*@C
6640: MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6641: each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6643: Not Collective, unless matrix has not been allocated, then collective on Mat
6645: Input Parameters:
6646: . mat - the matrix
6648: Output Parameters:
6649: . ranges - start of each processors portion plus one more then the total length at the end
6651: Level: beginner
6653: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6654: @*/
6655: PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6656: {
6659: MatCheckPreallocated(mat, 1);
6660: PetscLayoutGetRanges(mat->cmap, ranges);
6661: return 0;
6662: }
6664: /*@C
6665: MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6666: corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6667: is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6669: Not Collective
6671: Input Parameter:
6672: . A - matrix
6674: Output Parameters:
6675: + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6676: - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6678: Level: intermediate
6680: .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6681: @*/
6682: PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6683: {
6684: PetscErrorCode (*f)(Mat, IS *, IS *);
6686: MatCheckPreallocated(A, 1);
6687: PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f);
6688: if (f) {
6689: (*f)(A, rows, cols);
6690: } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6691: if (rows) ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows);
6692: if (cols) ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols);
6693: }
6694: return 0;
6695: }
6697: /*@C
6698: MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6699: Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6700: to complete the factorization.
6702: Collective on fact
6704: Input Parameters:
6705: + fact - the factorized matrix obtained with `MatGetFactor()`
6706: . mat - the matrix
6707: . row - row permutation
6708: . column - column permutation
6709: - info - structure containing
6710: $ levels - number of levels of fill.
6711: $ expected fill - as ratio of original fill.
6712: $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6713: missing diagonal entries)
6715: Output Parameters:
6716: . fact - new matrix that has been symbolically factored
6718: Level: developer
6720: Notes:
6721: See [Matrix Factorization](sec_matfactor) for additional information.
6723: Most users should employ the `KSP` interface for linear solvers
6724: instead of working directly with matrix algebra routines such as this.
6725: See, e.g., `KSPCreate()`.
6727: Uses the definition of level of fill as in Y. Saad, 2003
6729: Developer Note:
6730: The Fortran interface is not autogenerated as the
6731: interface definition cannot be generated correctly [due to `MatFactorInfo`]
6733: References:
6734: . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6736: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6737: `MatGetOrdering()`, `MatFactorInfo`
6738: @*/
6739: PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6740: {
6749: if (!fact->ops->ilufactorsymbolic) {
6750: MatSolverType stype;
6751: MatFactorGetSolverType(fact, &stype);
6752: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6753: }
6756: MatCheckPreallocated(mat, 2);
6758: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0);
6759: (fact->ops->ilufactorsymbolic)(fact, mat, row, col, info);
6760: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0);
6761: return 0;
6762: }
6764: /*@C
6765: MatICCFactorSymbolic - Performs symbolic incomplete
6766: Cholesky factorization for a symmetric matrix. Use
6767: `MatCholeskyFactorNumeric()` to complete the factorization.
6769: Collective on fact
6771: Input Parameters:
6772: + fact - the factorized matrix obtained with `MatGetFactor()`
6773: . mat - the matrix to be factored
6774: . perm - row and column permutation
6775: - info - structure containing
6776: $ levels - number of levels of fill.
6777: $ expected fill - as ratio of original fill.
6779: Output Parameter:
6780: . fact - the factored matrix
6782: Level: developer
6784: Notes:
6785: Most users should employ the `KSP` interface for linear solvers
6786: instead of working directly with matrix algebra routines such as this.
6787: See, e.g., `KSPCreate()`.
6789: This uses the definition of level of fill as in Y. Saad, 2003
6791: Developer Note:
6792: The Fortran interface is not autogenerated as the
6793: interface definition cannot be generated correctly [due to `MatFactorInfo`]
6795: References:
6796: . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6798: .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6799: @*/
6800: PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6801: {
6810: if (!(fact)->ops->iccfactorsymbolic) {
6811: MatSolverType stype;
6812: MatFactorGetSolverType(fact, &stype);
6813: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6814: }
6816: MatCheckPreallocated(mat, 2);
6818: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6819: (fact->ops->iccfactorsymbolic)(fact, mat, perm, info);
6820: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6821: return 0;
6822: }
6824: /*@C
6825: MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6826: points to an array of valid matrices, they may be reused to store the new
6827: submatrices.
6829: Collective
6831: Input Parameters:
6832: + mat - the matrix
6833: . n - the number of submatrixes to be extracted (on this processor, may be zero)
6834: . irow, icol - index sets of rows and columns to extract
6835: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6837: Output Parameter:
6838: . submat - the array of submatrices
6840: Notes:
6841: `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6842: (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6843: to extract a parallel submatrix.
6845: Some matrix types place restrictions on the row and column
6846: indices, such as that they be sorted or that they be equal to each other.
6848: The index sets may not have duplicate entries.
6850: When extracting submatrices from a parallel matrix, each processor can
6851: form a different submatrix by setting the rows and columns of its
6852: individual index sets according to the local submatrix desired.
6854: When finished using the submatrices, the user should destroy
6855: them with `MatDestroySubMatrices()`.
6857: `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6858: original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6860: This routine creates the matrices in submat; you should NOT create them before
6861: calling it. It also allocates the array of matrix pointers submat.
6863: For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6864: request one row/column in a block, they must request all rows/columns that are in
6865: that block. For example, if the block size is 2 you cannot request just row 0 and
6866: column 0.
6868: Fortran Note:
6869: The Fortran interface is slightly different from that given below; it
6870: requires one to pass in as submat a `Mat` (integer) array of size at least n+1.
6872: Level: advanced
6874: .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6875: @*/
6876: PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6877: {
6878: PetscInt i;
6879: PetscBool eq;
6883: if (n) {
6888: }
6890: if (n && scall == MAT_REUSE_MATRIX) {
6893: }
6896: MatCheckPreallocated(mat, 1);
6897: PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6898: PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6899: PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6900: for (i = 0; i < n; i++) {
6901: (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6902: ISEqualUnsorted(irow[i], icol[i], &eq);
6903: if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6904: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
6905: if (mat->boundtocpu && mat->bindingpropagates) {
6906: MatBindToCPU((*submat)[i], PETSC_TRUE);
6907: MatSetBindingPropagates((*submat)[i], PETSC_TRUE);
6908: }
6909: #endif
6910: }
6911: return 0;
6912: }
6914: /*@C
6915: MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
6917: Collective
6919: Input Parameters:
6920: + mat - the matrix
6921: . n - the number of submatrixes to be extracted
6922: . irow, icol - index sets of rows and columns to extract
6923: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6925: Output Parameter:
6926: . submat - the array of submatrices
6928: Level: advanced
6930: Note:
6931: This is used by `PCGASM`
6933: .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6934: @*/
6935: PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6936: {
6937: PetscInt i;
6938: PetscBool eq;
6942: if (n) {
6947: }
6949: if (n && scall == MAT_REUSE_MATRIX) {
6952: }
6955: MatCheckPreallocated(mat, 1);
6957: PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6958: PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6959: PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6960: for (i = 0; i < n; i++) {
6961: ISEqualUnsorted(irow[i], icol[i], &eq);
6962: if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6963: }
6964: return 0;
6965: }
6967: /*@C
6968: MatDestroyMatrices - Destroys an array of matrices.
6970: Collective
6972: Input Parameters:
6973: + n - the number of local matrices
6974: - mat - the matrices (note that this is a pointer to the array of matrices)
6976: Level: advanced
6978: Note:
6979: Frees not only the matrices, but also the array that contains the matrices
6980: In Fortran will not free the array.
6982: .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6983: @*/
6984: PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
6985: {
6986: PetscInt i;
6988: if (!*mat) return 0;
6992: for (i = 0; i < n; i++) MatDestroy(&(*mat)[i]);
6994: /* memory is allocated even if n = 0 */
6995: PetscFree(*mat);
6996: return 0;
6997: }
6999: /*@C
7000: MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7002: Collective
7004: Input Parameters:
7005: + n - the number of local matrices
7006: - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7007: sequence of MatCreateSubMatrices())
7009: Level: advanced
7011: Note:
7012: Frees not only the matrices, but also the array that contains the matrices
7013: In Fortran will not free the array.
7015: .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7016: @*/
7017: PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7018: {
7019: Mat mat0;
7021: if (!*mat) return 0;
7022: /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7026: mat0 = (*mat)[0];
7027: if (mat0 && mat0->ops->destroysubmatrices) {
7028: (mat0->ops->destroysubmatrices)(n, mat);
7029: } else {
7030: MatDestroyMatrices(n, mat);
7031: }
7032: return 0;
7033: }
7035: /*@C
7036: MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7038: Collective
7040: Input Parameters:
7041: . mat - the matrix
7043: Output Parameter:
7044: . matstruct - the sequential matrix with the nonzero structure of mat
7046: Level: developer
7048: .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7049: @*/
7050: PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7051: {
7057: MatCheckPreallocated(mat, 1);
7059: PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7060: PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7061: PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7062: return 0;
7063: }
7065: /*@C
7066: MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7068: Collective
7070: Input Parameters:
7071: . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7072: sequence of `MatGetSequentialNonzeroStructure()`)
7074: Level: advanced
7076: Note:
7077: Frees not only the matrices, but also the array that contains the matrices
7079: .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7080: @*/
7081: PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7082: {
7084: MatDestroy(mat);
7085: return 0;
7086: }
7088: /*@
7089: MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7090: replaces the index sets by larger ones that represent submatrices with
7091: additional overlap.
7093: Collective
7095: Input Parameters:
7096: + mat - the matrix
7097: . n - the number of index sets
7098: . is - the array of index sets (these index sets will changed during the call)
7099: - ov - the additional overlap requested
7101: Options Database Key:
7102: . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7104: Level: developer
7106: Note:
7107: The computed overlap preserves the matrix block sizes when the blocks are square.
7108: That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7109: that block are included in the overlap regardless of whether each specific column would increase the overlap.
7111: .seealso: `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7112: @*/
7113: PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7114: {
7115: PetscInt i, bs, cbs;
7121: if (n) {
7124: }
7127: MatCheckPreallocated(mat, 1);
7129: if (!ov || !n) return 0;
7130: PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7131: PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7132: PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7133: MatGetBlockSizes(mat, &bs, &cbs);
7134: if (bs == cbs) {
7135: for (i = 0; i < n; i++) ISSetBlockSize(is[i], bs);
7136: }
7137: return 0;
7138: }
7140: PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7142: /*@
7143: MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7144: a sub communicator, replaces the index sets by larger ones that represent submatrices with
7145: additional overlap.
7147: Collective
7149: Input Parameters:
7150: + mat - the matrix
7151: . n - the number of index sets
7152: . is - the array of index sets (these index sets will changed during the call)
7153: - ov - the additional overlap requested
7155: ` Options Database Key:
7156: . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7158: Level: developer
7160: .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7161: @*/
7162: PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7163: {
7164: PetscInt i;
7169: if (n) {
7172: }
7175: MatCheckPreallocated(mat, 1);
7176: if (!ov) return 0;
7177: PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7178: for (i = 0; i < n; i++) MatIncreaseOverlapSplit_Single(mat, &is[i], ov);
7179: PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7180: return 0;
7181: }
7183: /*@
7184: MatGetBlockSize - Returns the matrix block size.
7186: Not Collective
7188: Input Parameter:
7189: . mat - the matrix
7191: Output Parameter:
7192: . bs - block size
7194: Notes:
7195: Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7197: If the block size has not been set yet this routine returns 1.
7199: Level: intermediate
7201: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7202: @*/
7203: PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7204: {
7207: *bs = PetscAbs(mat->rmap->bs);
7208: return 0;
7209: }
7211: /*@
7212: MatGetBlockSizes - Returns the matrix block row and column sizes.
7214: Not Collective
7216: Input Parameter:
7217: . mat - the matrix
7219: Output Parameters:
7220: + rbs - row block size
7221: - cbs - column block size
7223: Notes:
7224: Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7225: If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7227: If a block size has not been set yet this routine returns 1.
7229: Level: intermediate
7231: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7232: @*/
7233: PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7234: {
7238: if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7239: if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7240: return 0;
7241: }
7243: /*@
7244: MatSetBlockSize - Sets the matrix block size.
7246: Logically Collective
7248: Input Parameters:
7249: + mat - the matrix
7250: - bs - block size
7252: Notes:
7253: Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7254: This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7256: For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7257: is compatible with the matrix local sizes.
7259: Level: intermediate
7261: .seealso: `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7262: @*/
7263: PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7264: {
7267: MatSetBlockSizes(mat, bs, bs);
7268: return 0;
7269: }
7271: typedef struct {
7272: PetscInt n;
7273: IS *is;
7274: Mat *mat;
7275: PetscObjectState nonzerostate;
7276: Mat C;
7277: } EnvelopeData;
7279: static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7280: {
7281: for (PetscInt i = 0; i < edata->n; i++) ISDestroy(&edata->is[i]);
7282: PetscFree(edata->is);
7283: PetscFree(edata);
7284: return 0;
7285: }
7287: /*
7288: MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7289: the sizes of these blocks in the matrix. An individual block may lie over several processes.
7291: Collective
7293: Input Parameter:
7294: . mat - the matrix
7296: Notes:
7297: There can be zeros within the blocks
7299: The blocks can overlap between processes, including laying on more than two processes
7301: .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7302: */
7303: static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7304: {
7305: PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7306: PetscInt *diag, *odiag, sc;
7307: VecScatter scatter;
7308: PetscScalar *seqv;
7309: const PetscScalar *parv;
7310: const PetscInt *ia, *ja;
7311: PetscBool set, flag, done;
7312: Mat AA = mat, A;
7313: MPI_Comm comm;
7314: PetscMPIInt rank, size, tag;
7315: MPI_Status status;
7316: PetscContainer container;
7317: EnvelopeData *edata;
7318: Vec seq, par;
7319: IS isglobal;
7322: MatIsSymmetricKnown(mat, &set, &flag);
7323: if (!set || !flag) {
7324: /* TOO: only needs nonzero structure of transpose */
7325: MatTranspose(mat, MAT_INITIAL_MATRIX, &AA);
7326: MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN);
7327: }
7328: MatAIJGetLocalMat(AA, &A);
7329: MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7332: MatGetLocalSize(mat, &n, NULL);
7333: PetscObjectGetNewTag((PetscObject)mat, &tag);
7334: PetscObjectGetComm((PetscObject)mat, &comm);
7335: MPI_Comm_size(comm, &size);
7336: MPI_Comm_rank(comm, &rank);
7338: PetscMalloc2(n, &sizes, n, &starts);
7340: if (rank > 0) {
7341: MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status);
7342: MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status);
7343: }
7344: MatGetOwnershipRange(mat, &rstart, NULL);
7345: for (i = 0; i < n; i++) {
7346: env = PetscMax(env, ja[ia[i + 1] - 1]);
7347: II = rstart + i;
7348: if (env == II) {
7349: starts[lblocks] = tbs;
7350: sizes[lblocks++] = 1 + II - tbs;
7351: tbs = 1 + II;
7352: }
7353: }
7354: if (rank < size - 1) {
7355: MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm);
7356: MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm);
7357: }
7359: MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7360: if (!set || !flag) MatDestroy(&AA);
7361: MatDestroy(&A);
7363: PetscNew(&edata);
7364: MatGetNonzeroState(mat, &edata->nonzerostate);
7365: edata->n = lblocks;
7366: /* create IS needed for extracting blocks from the original matrix */
7367: PetscMalloc1(lblocks, &edata->is);
7368: for (PetscInt i = 0; i < lblocks; i++) ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]);
7370: /* Create the resulting inverse matrix structure with preallocation information */
7371: MatCreate(PetscObjectComm((PetscObject)mat), &edata->C);
7372: MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
7373: MatSetBlockSizesFromMats(edata->C, mat, mat);
7374: MatSetType(edata->C, MATAIJ);
7376: /* Communicate the start and end of each row, from each block to the correct rank */
7377: /* TODO: Use PetscSF instead of VecScatter */
7378: for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7379: VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq);
7380: VecGetArrayWrite(seq, &seqv);
7381: for (PetscInt i = 0; i < lblocks; i++) {
7382: for (PetscInt j = 0; j < sizes[i]; j++) {
7383: seqv[cnt] = starts[i];
7384: seqv[cnt + 1] = starts[i] + sizes[i];
7385: cnt += 2;
7386: }
7387: }
7388: VecRestoreArrayWrite(seq, &seqv);
7389: MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
7390: sc -= cnt;
7391: VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par);
7392: ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal);
7393: VecScatterCreate(seq, NULL, par, isglobal, &scatter);
7394: ISDestroy(&isglobal);
7395: VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7396: VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7397: VecScatterDestroy(&scatter);
7398: VecDestroy(&seq);
7399: MatGetOwnershipRangeColumn(mat, &cstart, &cend);
7400: PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag);
7401: VecGetArrayRead(par, &parv);
7402: cnt = 0;
7403: MatGetSize(mat, NULL, &n);
7404: for (PetscInt i = 0; i < mat->rmap->n; i++) {
7405: PetscInt start, end, d = 0, od = 0;
7407: start = (PetscInt)PetscRealPart(parv[cnt]);
7408: end = (PetscInt)PetscRealPart(parv[cnt + 1]);
7409: cnt += 2;
7411: if (start < cstart) {
7412: od += cstart - start + n - cend;
7413: d += cend - cstart;
7414: } else if (start < cend) {
7415: od += n - cend;
7416: d += cend - start;
7417: } else od += n - start;
7418: if (end <= cstart) {
7419: od -= cstart - end + n - cend;
7420: d -= cend - cstart;
7421: } else if (end < cend) {
7422: od -= n - cend;
7423: d -= cend - end;
7424: } else od -= n - end;
7426: odiag[i] = od;
7427: diag[i] = d;
7428: }
7429: VecRestoreArrayRead(par, &parv);
7430: VecDestroy(&par);
7431: MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL);
7432: PetscFree2(diag, odiag);
7433: PetscFree2(sizes, starts);
7435: PetscContainerCreate(PETSC_COMM_SELF, &container);
7436: PetscContainerSetPointer(container, edata);
7437: PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy);
7438: PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container);
7439: PetscObjectDereference((PetscObject)container);
7440: return 0;
7441: }
7443: /*@
7444: MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7446: Collective on A
7448: Input Parameters:
7449: . A - the matrix
7451: Output Parameters:
7452: . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set.
7454: Note:
7455: For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7457: Level: advanced
7459: .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7460: @*/
7461: PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7462: {
7463: PetscContainer container;
7464: EnvelopeData *edata;
7465: PetscObjectState nonzerostate;
7467: PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7468: if (!container) {
7469: MatComputeVariableBlockEnvelope(A);
7470: PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7471: }
7472: PetscContainerGetPointer(container, (void **)&edata);
7473: MatGetNonzeroState(A, &nonzerostate);
7477: MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat);
7478: *C = edata->C;
7480: for (PetscInt i = 0; i < edata->n; i++) {
7481: Mat D;
7482: PetscScalar *dvalues;
7484: MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D);
7485: MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE);
7486: MatSeqDenseInvert(D);
7487: MatDenseGetArray(D, &dvalues);
7488: MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES);
7489: MatDestroy(&D);
7490: }
7491: MatDestroySubMatrices(edata->n, &edata->mat);
7492: MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY);
7493: MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY);
7494: return 0;
7495: }
7497: /*@
7498: MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7500: Logically Collective
7502: Input Parameters:
7503: + mat - the matrix
7504: . nblocks - the number of blocks on this process, each block can only exist on a single process
7505: - bsizes - the block sizes
7507: Notes:
7508: Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7510: 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.
7512: Level: intermediate
7514: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7515: `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7516: @*/
7517: PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7518: {
7519: PetscInt i, ncnt = 0, nlocal;
7523: MatGetLocalSize(mat, &nlocal, NULL);
7524: for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7526: PetscFree(mat->bsizes);
7527: mat->nblocks = nblocks;
7528: PetscMalloc1(nblocks, &mat->bsizes);
7529: PetscArraycpy(mat->bsizes, bsizes, nblocks);
7530: return 0;
7531: }
7533: /*@C
7534: MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7536: Logically Collective; No Fortran Support
7538: Input Parameter:
7539: . mat - the matrix
7541: Output Parameters:
7542: + nblocks - the number of blocks on this process
7543: - bsizes - the block sizes
7545: Level: intermediate
7547: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7548: @*/
7549: PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7550: {
7552: *nblocks = mat->nblocks;
7553: *bsizes = mat->bsizes;
7554: return 0;
7555: }
7557: /*@
7558: MatSetBlockSizes - Sets the matrix block row and column sizes.
7560: Logically Collective
7562: Input Parameters:
7563: + mat - the matrix
7564: . rbs - row block size
7565: - cbs - column block size
7567: Notes:
7568: Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7569: If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7570: This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7572: For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7573: are compatible with the matrix local sizes.
7575: The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7577: Level: intermediate
7579: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7580: @*/
7581: PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7582: {
7586: PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7587: if (mat->rmap->refcnt) {
7588: ISLocalToGlobalMapping l2g = NULL;
7589: PetscLayout nmap = NULL;
7591: PetscLayoutDuplicate(mat->rmap, &nmap);
7592: if (mat->rmap->mapping) ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g);
7593: PetscLayoutDestroy(&mat->rmap);
7594: mat->rmap = nmap;
7595: mat->rmap->mapping = l2g;
7596: }
7597: if (mat->cmap->refcnt) {
7598: ISLocalToGlobalMapping l2g = NULL;
7599: PetscLayout nmap = NULL;
7601: PetscLayoutDuplicate(mat->cmap, &nmap);
7602: if (mat->cmap->mapping) ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g);
7603: PetscLayoutDestroy(&mat->cmap);
7604: mat->cmap = nmap;
7605: mat->cmap->mapping = l2g;
7606: }
7607: PetscLayoutSetBlockSize(mat->rmap, rbs);
7608: PetscLayoutSetBlockSize(mat->cmap, cbs);
7609: return 0;
7610: }
7612: /*@
7613: MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7615: Logically Collective
7617: Input Parameters:
7618: + mat - the matrix
7619: . fromRow - matrix from which to copy row block size
7620: - fromCol - matrix from which to copy column block size (can be same as fromRow)
7622: Level: developer
7624: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7625: @*/
7626: PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7627: {
7631: if (fromRow->rmap->bs > 0) PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs);
7632: if (fromCol->cmap->bs > 0) PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs);
7633: return 0;
7634: }
7636: /*@
7637: MatResidual - Default routine to calculate the residual r = b - Ax
7639: Collective
7641: Input Parameters:
7642: + mat - the matrix
7643: . b - the right-hand-side
7644: - x - the approximate solution
7646: Output Parameter:
7647: . r - location to store the residual
7649: Level: developer
7651: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7652: @*/
7653: PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7654: {
7660: MatCheckPreallocated(mat, 1);
7661: PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0);
7662: if (!mat->ops->residual) {
7663: MatMult(mat, x, r);
7664: VecAYPX(r, -1.0, b);
7665: } else {
7666: PetscUseTypeMethod(mat, residual, b, x, r);
7667: }
7668: PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0);
7669: return 0;
7670: }
7672: /*@C
7673: MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7675: Collective
7677: Input Parameters:
7678: + mat - the matrix
7679: . shift - 0 or 1 indicating we want the indices starting at 0 or 1
7680: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7681: - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the
7682: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7683: always used.
7685: Output Parameters:
7686: + n - number of local rows in the (possibly compressed) matrix, use NULL if not needed
7687: . 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
7688: . ja - the column indices, use NULL if not needed
7689: - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7690: are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7692: Level: developer
7694: Notes:
7695: You CANNOT change any of the ia[] or ja[] values.
7697: Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7699: Fortran Notes:
7700: In Fortran use
7701: .vb
7702: PetscInt ia(1), ja(1)
7703: PetscOffset iia, jja
7704: call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7705: ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7706: .ve
7707: or
7708: .vb
7709: PetscInt, pointer :: ia(:),ja(:)
7710: call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7711: ! Access the ith and jth entries via ia(i) and ja(j)
7712: .ve
7714: .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7715: @*/
7716: PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7717: {
7724: MatCheckPreallocated(mat, 1);
7725: if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7726: else {
7727: if (done) *done = PETSC_TRUE;
7728: PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0);
7729: PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7730: PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0);
7731: }
7732: return 0;
7733: }
7735: /*@C
7736: MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7738: Collective
7740: Input Parameters:
7741: + mat - the matrix
7742: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7743: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7744: symmetrized
7745: . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7746: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7747: always used.
7748: . n - number of columns in the (possibly compressed) matrix
7749: . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7750: - ja - the row indices
7752: Output Parameters:
7753: . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7755: Level: developer
7757: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7758: @*/
7759: PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7760: {
7767: MatCheckPreallocated(mat, 1);
7768: if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7769: else {
7770: *done = PETSC_TRUE;
7771: PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7772: }
7773: return 0;
7774: }
7776: /*@C
7777: MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7779: Collective
7781: Input Parameters:
7782: + mat - the matrix
7783: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7784: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7785: . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7786: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7787: always used.
7788: . n - size of (possibly compressed) matrix
7789: . ia - the row pointers
7790: - ja - the column indices
7792: Output Parameters:
7793: . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7795: Note:
7796: This routine zeros out n, ia, and ja. This is to prevent accidental
7797: us of the array after it has been restored. If you pass NULL, it will
7798: not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7800: Level: developer
7802: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7803: @*/
7804: PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7805: {
7811: MatCheckPreallocated(mat, 1);
7813: if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7814: else {
7815: if (done) *done = PETSC_TRUE;
7816: PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7817: if (n) *n = 0;
7818: if (ia) *ia = NULL;
7819: if (ja) *ja = NULL;
7820: }
7821: return 0;
7822: }
7824: /*@C
7825: MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
7827: Collective on Mat
7829: Input Parameters:
7830: + mat - the matrix
7831: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7832: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7833: - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7834: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7835: always used.
7837: Output Parameters:
7838: + n - size of (possibly compressed) matrix
7839: . ia - the column pointers
7840: . ja - the row indices
7841: - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7843: Level: developer
7845: .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7846: @*/
7847: PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7848: {
7854: MatCheckPreallocated(mat, 1);
7856: if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7857: else {
7858: *done = PETSC_TRUE;
7859: PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7860: if (n) *n = 0;
7861: if (ia) *ia = NULL;
7862: if (ja) *ja = NULL;
7863: }
7864: return 0;
7865: }
7867: /*@C
7868: MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
7870: Collective
7872: Input Parameters:
7873: + mat - the matrix
7874: . ncolors - max color value
7875: . n - number of entries in colorarray
7876: - colorarray - array indicating color for each column
7878: Output Parameters:
7879: . iscoloring - coloring generated using colorarray information
7881: Level: developer
7883: .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7884: @*/
7885: PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
7886: {
7891: MatCheckPreallocated(mat, 1);
7893: if (!mat->ops->coloringpatch) {
7894: ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring);
7895: } else {
7896: PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7897: }
7898: return 0;
7899: }
7901: /*@
7902: MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
7904: Logically Collective
7906: Input Parameter:
7907: . mat - the factored matrix to be reset
7909: Notes:
7910: This routine should be used only with factored matrices formed by in-place
7911: factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
7912: format). This option can save memory, for example, when solving nonlinear
7913: systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7914: ILU(0) preconditioner.
7916: Note that one can specify in-place ILU(0) factorization by calling
7917: .vb
7918: PCType(pc,PCILU);
7919: PCFactorSeUseInPlace(pc);
7920: .ve
7921: or by using the options -pc_type ilu -pc_factor_in_place
7923: In-place factorization ILU(0) can also be used as a local
7924: solver for the blocks within the block Jacobi or additive Schwarz
7925: methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc
7926: for details on setting local solver options.
7928: Most users should employ the `KSP` interface for linear solvers
7929: instead of working directly with matrix algebra routines such as this.
7930: See, e.g., `KSPCreate()`.
7932: Level: developer
7934: .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7935: @*/
7936: PetscErrorCode MatSetUnfactored(Mat mat)
7937: {
7940: MatCheckPreallocated(mat, 1);
7941: mat->factortype = MAT_FACTOR_NONE;
7942: if (!mat->ops->setunfactored) return 0;
7943: PetscUseTypeMethod(mat, setunfactored);
7944: return 0;
7945: }
7947: /*MC
7948: MatDenseGetArrayF90 - Accesses a matrix array from Fortran
7950: Synopsis:
7951: MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7953: Not collective
7955: Input Parameter:
7956: . x - matrix
7958: Output Parameters:
7959: + xx_v - the Fortran pointer to the array
7960: - ierr - error code
7962: Example of Usage:
7963: .vb
7964: PetscScalar, pointer xx_v(:,:)
7965: ....
7966: call MatDenseGetArrayF90(x,xx_v,ierr)
7967: a = xx_v(3)
7968: call MatDenseRestoreArrayF90(x,xx_v,ierr)
7969: .ve
7971: Level: advanced
7973: .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
7975: M*/
7977: /*MC
7978: MatDenseRestoreArrayF90 - Restores a matrix array that has been
7979: accessed with `MatDenseGetArrayF90()`.
7981: Synopsis:
7982: MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7984: Not collective
7986: Input Parameters:
7987: + x - matrix
7988: - xx_v - the Fortran90 pointer to the array
7990: Output Parameter:
7991: . ierr - error code
7993: Example of Usage:
7994: .vb
7995: PetscScalar, pointer xx_v(:,:)
7996: ....
7997: call MatDenseGetArrayF90(x,xx_v,ierr)
7998: a = xx_v(3)
7999: call MatDenseRestoreArrayF90(x,xx_v,ierr)
8000: .ve
8002: Level: advanced
8004: .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8006: M*/
8008: /*MC
8009: MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8011: Synopsis:
8012: MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8014: Not collective
8016: Input Parameter:
8017: . x - matrix
8019: Output Parameters:
8020: + xx_v - the Fortran pointer to the array
8021: - ierr - error code
8023: Example of Usage:
8024: .vb
8025: PetscScalar, pointer xx_v(:)
8026: ....
8027: call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8028: a = xx_v(3)
8029: call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8030: .ve
8032: Level: advanced
8034: .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8036: M*/
8038: /*MC
8039: MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8040: accessed with `MatSeqAIJGetArrayF90()`.
8042: Synopsis:
8043: MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8045: Not collective
8047: Input Parameters:
8048: + x - matrix
8049: - xx_v - the Fortran90 pointer to the array
8051: Output Parameter:
8052: . ierr - error code
8054: Example of Usage:
8055: .vb
8056: PetscScalar, pointer xx_v(:)
8057: ....
8058: call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8059: a = xx_v(3)
8060: call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8061: .ve
8063: Level: advanced
8065: .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8067: M*/
8069: /*@
8070: MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8071: as the original matrix.
8073: Collective
8075: Input Parameters:
8076: + mat - the original matrix
8077: . isrow - parallel IS containing the rows this processor should obtain
8078: . 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.
8079: - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8081: Output Parameter:
8082: . newmat - the new submatrix, of the same type as the old
8084: Level: advanced
8086: Notes:
8087: The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8089: Some matrix types place restrictions on the row and column indices, such
8090: as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block;
8091: for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8093: The index sets may not have duplicate entries.
8095: The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8096: the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8097: to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8098: will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when
8099: you are finished using it.
8101: The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8102: the input matrix.
8104: If iscol is NULL then all columns are obtained (not supported in Fortran).
8106: Example usage:
8107: Consider the following 8x8 matrix with 34 non-zero values, that is
8108: assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8109: proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8110: as follows:
8112: .vb
8113: 1 2 0 | 0 3 0 | 0 4
8114: Proc0 0 5 6 | 7 0 0 | 8 0
8115: 9 0 10 | 11 0 0 | 12 0
8116: -------------------------------------
8117: 13 0 14 | 15 16 17 | 0 0
8118: Proc1 0 18 0 | 19 20 21 | 0 0
8119: 0 0 0 | 22 23 0 | 24 0
8120: -------------------------------------
8121: Proc2 25 26 27 | 0 0 28 | 29 0
8122: 30 0 0 | 31 32 33 | 0 34
8123: .ve
8125: Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is
8127: .vb
8128: 2 0 | 0 3 0 | 0
8129: Proc0 5 6 | 7 0 0 | 8
8130: -------------------------------
8131: Proc1 18 0 | 19 20 21 | 0
8132: -------------------------------
8133: Proc2 26 27 | 0 0 28 | 29
8134: 0 0 | 31 32 33 | 0
8135: .ve
8137: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8138: @*/
8139: PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8140: {
8141: PetscMPIInt size;
8142: Mat *local;
8143: IS iscoltmp;
8144: PetscBool flg;
8155: MatCheckPreallocated(mat, 1);
8156: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8158: if (!iscol || isrow == iscol) {
8159: PetscBool stride;
8160: PetscMPIInt grabentirematrix = 0, grab;
8161: PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride);
8162: if (stride) {
8163: PetscInt first, step, n, rstart, rend;
8164: ISStrideGetInfo(isrow, &first, &step);
8165: if (step == 1) {
8166: MatGetOwnershipRange(mat, &rstart, &rend);
8167: if (rstart == first) {
8168: ISGetLocalSize(isrow, &n);
8169: if (n == rend - rstart) grabentirematrix = 1;
8170: }
8171: }
8172: }
8173: MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat));
8174: if (grab) {
8175: PetscInfo(mat, "Getting entire matrix as submatrix\n");
8176: if (cll == MAT_INITIAL_MATRIX) {
8177: *newmat = mat;
8178: PetscObjectReference((PetscObject)mat);
8179: }
8180: return 0;
8181: }
8182: }
8184: if (!iscol) {
8185: ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp);
8186: } else {
8187: iscoltmp = iscol;
8188: }
8190: /* if original matrix is on just one processor then use submatrix generated */
8191: if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8192: MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat);
8193: goto setproperties;
8194: } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8195: MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local);
8196: *newmat = *local;
8197: PetscFree(local);
8198: goto setproperties;
8199: } else if (!mat->ops->createsubmatrix) {
8200: /* Create a new matrix type that implements the operation using the full matrix */
8201: PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8202: switch (cll) {
8203: case MAT_INITIAL_MATRIX:
8204: MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat);
8205: break;
8206: case MAT_REUSE_MATRIX:
8207: MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp);
8208: break;
8209: default:
8210: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8211: }
8212: PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8213: goto setproperties;
8214: }
8216: PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8217: PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8218: PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8220: setproperties:
8221: ISEqualUnsorted(isrow, iscoltmp, &flg);
8222: if (flg) MatPropagateSymmetryOptions(mat, *newmat);
8223: if (!iscol) ISDestroy(&iscoltmp);
8224: if (*newmat && cll == MAT_INITIAL_MATRIX) PetscObjectStateIncrease((PetscObject)*newmat);
8225: return 0;
8226: }
8228: /*@
8229: MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8231: Not Collective
8233: Input Parameters:
8234: + A - the matrix we wish to propagate options from
8235: - B - the matrix we wish to propagate options to
8237: Level: beginner
8239: Note:
8240: Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8242: .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8243: @*/
8244: PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8245: {
8248: B->symmetry_eternal = A->symmetry_eternal;
8249: B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8250: B->symmetric = A->symmetric;
8251: B->structurally_symmetric = A->structurally_symmetric;
8252: B->spd = A->spd;
8253: B->hermitian = A->hermitian;
8254: return 0;
8255: }
8257: /*@
8258: MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8259: used during the assembly process to store values that belong to
8260: other processors.
8262: Not Collective
8264: Input Parameters:
8265: + mat - the matrix
8266: . size - the initial size of the stash.
8267: - bsize - the initial size of the block-stash(if used).
8269: Options Database Keys:
8270: + -matstash_initial_size <size> or <size0,size1,...sizep-1>
8271: - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1>
8273: Level: intermediate
8275: Notes:
8276: The block-stash is used for values set with `MatSetValuesBlocked()` while
8277: the stash is used for values set with `MatSetValues()`
8279: Run with the option -info and look for output of the form
8280: MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8281: to determine the appropriate value, MM, to use for size and
8282: MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8283: to determine the value, BMM to use for bsize
8285: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8286: @*/
8287: PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8288: {
8291: MatStashSetInitialSize_Private(&mat->stash, size);
8292: MatStashSetInitialSize_Private(&mat->bstash, bsize);
8293: return 0;
8294: }
8296: /*@
8297: MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8298: the matrix
8300: Neighbor-wise Collective
8302: Input Parameters:
8303: + mat - the matrix
8304: . x,y - the vectors
8305: - w - where the result is stored
8307: Level: intermediate
8309: Notes:
8310: w may be the same vector as y.
8312: This allows one to use either the restriction or interpolation (its transpose)
8313: matrix to do the interpolation
8315: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8316: @*/
8317: PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8318: {
8319: PetscInt M, N, Ny;
8325: MatGetSize(A, &M, &N);
8326: VecGetSize(y, &Ny);
8327: if (M == Ny) {
8328: MatMultAdd(A, x, y, w);
8329: } else {
8330: MatMultTransposeAdd(A, x, y, w);
8331: }
8332: return 0;
8333: }
8335: /*@
8336: MatInterpolate - y = A*x or A'*x depending on the shape of
8337: the matrix
8339: Neighbor-wise Collective
8341: Input Parameters:
8342: + mat - the matrix
8343: - x,y - the vectors
8345: Level: intermediate
8347: Note:
8348: This allows one to use either the restriction or interpolation (its transpose)
8349: matrix to do the interpolation
8351: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8352: @*/
8353: PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8354: {
8355: PetscInt M, N, Ny;
8360: MatGetSize(A, &M, &N);
8361: VecGetSize(y, &Ny);
8362: if (M == Ny) {
8363: MatMult(A, x, y);
8364: } else {
8365: MatMultTranspose(A, x, y);
8366: }
8367: return 0;
8368: }
8370: /*@
8371: MatRestrict - y = A*x or A'*x
8373: Neighbor-wise Collective on Mat
8375: Input Parameters:
8376: + mat - the matrix
8377: - x,y - the vectors
8379: Level: intermediate
8381: Note:
8382: This allows one to use either the restriction or interpolation (its transpose)
8383: matrix to do the restriction
8385: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8386: @*/
8387: PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8388: {
8389: PetscInt M, N, Ny;
8394: MatGetSize(A, &M, &N);
8395: VecGetSize(y, &Ny);
8396: if (M == Ny) {
8397: MatMult(A, x, y);
8398: } else {
8399: MatMultTranspose(A, x, y);
8400: }
8401: return 0;
8402: }
8404: /*@
8405: MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8407: Neighbor-wise Collective on Mat
8409: Input Parameters:
8410: + mat - the matrix
8411: - w, x - the input dense matrices
8413: Output Parameters:
8414: . y - the output dense matrix
8416: Level: intermediate
8418: Note:
8419: This allows one to use either the restriction or interpolation (its transpose)
8420: matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8421: otherwise it will be recreated. y must be initialized to NULL if not supplied.
8423: .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8424: @*/
8425: PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8426: {
8427: PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8428: PetscBool trans = PETSC_TRUE;
8429: MatReuse reuse = MAT_INITIAL_MATRIX;
8436: MatGetSize(A, &M, &N);
8437: MatGetSize(x, &Mx, &Nx);
8438: if (N == Mx) trans = PETSC_FALSE;
8440: Mo = trans ? N : M;
8441: if (*y) {
8442: MatGetSize(*y, &My, &Ny);
8443: if (Mo == My && Nx == Ny) {
8444: reuse = MAT_REUSE_MATRIX;
8445: } else {
8447: MatDestroy(y);
8448: }
8449: }
8451: if (w && *y == w) { /* this is to minimize changes in PCMG */
8452: PetscBool flg;
8454: PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w);
8455: if (w) {
8456: PetscInt My, Ny, Mw, Nw;
8458: PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg);
8459: MatGetSize(*y, &My, &Ny);
8460: MatGetSize(w, &Mw, &Nw);
8461: if (!flg || My != Mw || Ny != Nw) w = NULL;
8462: }
8463: if (!w) {
8464: MatDuplicate(*y, MAT_COPY_VALUES, &w);
8465: PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w);
8466: PetscObjectDereference((PetscObject)w);
8467: } else {
8468: MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN);
8469: }
8470: }
8471: if (!trans) {
8472: MatMatMult(A, x, reuse, PETSC_DEFAULT, y);
8473: } else {
8474: MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y);
8475: }
8476: if (w) MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN);
8477: return 0;
8478: }
8480: /*@
8481: MatMatInterpolate - Y = A*X or A'*X
8483: Neighbor-wise Collective on Mat
8485: Input Parameters:
8486: + mat - the matrix
8487: - x - the input dense matrix
8489: Output Parameters:
8490: . y - the output dense matrix
8492: Level: intermediate
8494: Note:
8495: This allows one to use either the restriction or interpolation (its transpose)
8496: matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8497: otherwise it will be recreated. y must be initialized to NULL if not supplied.
8499: .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8500: @*/
8501: PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8502: {
8503: MatMatInterpolateAdd(A, x, NULL, y);
8504: return 0;
8505: }
8507: /*@
8508: MatMatRestrict - Y = A*X or A'*X
8510: Neighbor-wise Collective on Mat
8512: Input Parameters:
8513: + mat - the matrix
8514: - x - the input dense matrix
8516: Output Parameters:
8517: . y - the output dense matrix
8519: Level: intermediate
8521: Note:
8522: This allows one to use either the restriction or interpolation (its transpose)
8523: matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8524: otherwise it will be recreated. y must be initialized to NULL if not supplied.
8526: .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8527: @*/
8528: PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8529: {
8530: MatMatInterpolateAdd(A, x, NULL, y);
8531: return 0;
8532: }
8534: /*@
8535: MatGetNullSpace - retrieves the null space of a matrix.
8537: Logically Collective
8539: Input Parameters:
8540: + mat - the matrix
8541: - nullsp - the null space object
8543: Level: developer
8545: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8546: @*/
8547: PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8548: {
8551: *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8552: return 0;
8553: }
8555: /*@
8556: MatSetNullSpace - attaches a null space to a matrix.
8558: Logically Collective
8560: Input Parameters:
8561: + mat - the matrix
8562: - nullsp - the null space object
8564: Level: advanced
8566: Notes:
8567: This null space is used by the `KSP` linear solvers to solve singular systems.
8569: 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
8571: 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
8572: to zero but the linear system will still be solved in a least squares sense.
8574: The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8575: 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).
8576: 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
8577: 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
8578: 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).
8579: This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8581: If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8582: `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8583: routine also automatically calls `MatSetTransposeNullSpace()`.
8585: The user should call `MatNullSpaceDestroy()`.
8587: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8588: `KSPSetPCSide()`
8589: @*/
8590: PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8591: {
8594: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8595: MatNullSpaceDestroy(&mat->nullsp);
8596: mat->nullsp = nullsp;
8597: if (mat->symmetric == PETSC_BOOL3_TRUE) MatSetTransposeNullSpace(mat, nullsp);
8598: return 0;
8599: }
8601: /*@
8602: MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8604: Logically Collective
8606: Input Parameters:
8607: + mat - the matrix
8608: - nullsp - the null space object
8610: Level: developer
8612: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8613: @*/
8614: PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8615: {
8619: *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8620: return 0;
8621: }
8623: /*@
8624: MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8626: Logically Collective
8628: Input Parameters:
8629: + mat - the matrix
8630: - nullsp - the null space object
8632: Level: advanced
8634: Notes:
8635: This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8637: See `MatSetNullSpace()`
8639: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8640: @*/
8641: PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8642: {
8645: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8646: MatNullSpaceDestroy(&mat->transnullsp);
8647: mat->transnullsp = nullsp;
8648: return 0;
8649: }
8651: /*@
8652: MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8653: This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8655: Logically Collective
8657: Input Parameters:
8658: + mat - the matrix
8659: - nullsp - the null space object
8661: Level: advanced
8663: Notes:
8664: Overwrites any previous near null space that may have been attached
8666: You can remove the null space by calling this routine with an nullsp of NULL
8668: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8669: @*/
8670: PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8671: {
8675: MatCheckPreallocated(mat, 1);
8676: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8677: MatNullSpaceDestroy(&mat->nearnullsp);
8678: mat->nearnullsp = nullsp;
8679: return 0;
8680: }
8682: /*@
8683: MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8685: Not Collective
8687: Input Parameter:
8688: . mat - the matrix
8690: Output Parameter:
8691: . nullsp - the null space object, NULL if not set
8693: Level: advanced
8695: .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8696: @*/
8697: PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8698: {
8702: MatCheckPreallocated(mat, 1);
8703: *nullsp = mat->nearnullsp;
8704: return 0;
8705: }
8707: /*@C
8708: MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8710: Collective
8712: Input Parameters:
8713: + mat - the matrix
8714: . row - row/column permutation
8715: . fill - expected fill factor >= 1.0
8716: - level - level of fill, for ICC(k)
8718: Notes:
8719: Probably really in-place only when level of fill is zero, otherwise allocates
8720: new space to store factored matrix and deletes previous memory.
8722: Most users should employ the `KSP` interface for linear solvers
8723: instead of working directly with matrix algebra routines such as this.
8724: See, e.g., `KSPCreate()`.
8726: Level: developer
8728: Developer Note:
8729: The Fortran interface is not autogenerated as the
8730: interface definition cannot be generated correctly [due to `MatFactorInfo`]
8732: .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8733: @*/
8734: PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8735: {
8743: MatCheckPreallocated(mat, 1);
8744: PetscUseTypeMethod(mat, iccfactor, row, info);
8745: PetscObjectStateIncrease((PetscObject)mat);
8746: return 0;
8747: }
8749: /*@
8750: MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8751: ghosted ones.
8753: Not Collective
8755: Input Parameters:
8756: + mat - the matrix
8757: - diag - the diagonal values, including ghost ones
8759: Level: developer
8761: Notes:
8762: Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8764: This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8766: .seealso: `MatDiagonalScale()`
8767: @*/
8768: PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8769: {
8770: PetscMPIInt size;
8777: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
8778: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8779: if (size == 1) {
8780: PetscInt n, m;
8781: VecGetSize(diag, &n);
8782: MatGetSize(mat, NULL, &m);
8783: if (m == n) {
8784: MatDiagonalScale(mat, NULL, diag);
8785: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8786: } else {
8787: PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8788: }
8789: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
8790: PetscObjectStateIncrease((PetscObject)mat);
8791: return 0;
8792: }
8794: /*@
8795: MatGetInertia - Gets the inertia from a factored matrix
8797: Collective
8799: Input Parameter:
8800: . mat - the matrix
8802: Output Parameters:
8803: + nneg - number of negative eigenvalues
8804: . nzero - number of zero eigenvalues
8805: - npos - number of positive eigenvalues
8807: Level: advanced
8809: Note:
8810: Matrix must have been factored by `MatCholeskyFactor()`
8812: .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8813: @*/
8814: PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8815: {
8820: PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8821: return 0;
8822: }
8824: /* ----------------------------------------------------------------*/
8825: /*@C
8826: MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8828: Neighbor-wise Collective
8830: Input Parameters:
8831: + mat - the factored matrix obtained with `MatGetFactor()`
8832: - b - the right-hand-side vectors
8834: Output Parameter:
8835: . x - the result vectors
8837: Note:
8838: The vectors b and x cannot be the same. I.e., one cannot
8839: call `MatSolves`(A,x,x).
8841: Level: developer
8843: .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8844: @*/
8845: PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
8846: {
8851: if (!mat->rmap->N && !mat->cmap->N) return 0;
8853: MatCheckPreallocated(mat, 1);
8854: PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0);
8855: PetscUseTypeMethod(mat, solves, b, x);
8856: PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0);
8857: return 0;
8858: }
8860: /*@
8861: MatIsSymmetric - Test whether a matrix is symmetric
8863: Collective
8865: Input Parameters:
8866: + A - the matrix to test
8867: - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
8869: Output Parameters:
8870: . flg - the result
8872: Notes:
8873: For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8875: If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
8877: One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8878: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8880: Level: intermediate
8882: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
8883: `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8884: @*/
8885: PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
8886: {
8890: if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8891: else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8892: else {
8893: if (!A->ops->issymmetric) {
8894: MatType mattype;
8895: MatGetType(A, &mattype);
8896: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8897: }
8898: PetscUseTypeMethod(A, issymmetric, tol, flg);
8899: if (!tol) MatSetOption(A, MAT_SYMMETRIC, *flg);
8900: }
8901: return 0;
8902: }
8904: /*@
8905: MatIsHermitian - Test whether a matrix is Hermitian
8907: Collective on Mat
8909: Input Parameters:
8910: + A - the matrix to test
8911: - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
8913: Output Parameters:
8914: . flg - the result
8916: Level: intermediate
8918: Notes:
8919: For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8921: If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
8923: One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8924: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
8926: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8927: `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8928: @*/
8929: PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
8930: {
8934: if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8935: else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8936: else {
8937: if (!A->ops->ishermitian) {
8938: MatType mattype;
8939: MatGetType(A, &mattype);
8940: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8941: }
8942: PetscUseTypeMethod(A, ishermitian, tol, flg);
8943: if (!tol) MatSetOption(A, MAT_HERMITIAN, *flg);
8944: }
8945: return 0;
8946: }
8948: /*@
8949: MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
8951: Not Collective
8953: Input Parameter:
8954: . A - the matrix to check
8956: Output Parameters:
8957: + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
8958: - flg - the result (only valid if set is `PETSC_TRUE`)
8960: Level: advanced
8962: Notes:
8963: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
8964: if you want it explicitly checked
8966: One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8967: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8969: .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8970: @*/
8971: PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
8972: {
8976: if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8977: *set = PETSC_TRUE;
8978: *flg = PetscBool3ToBool(A->symmetric);
8979: } else {
8980: *set = PETSC_FALSE;
8981: }
8982: return 0;
8983: }
8985: /*@
8986: MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
8988: Not Collective
8990: Input Parameter:
8991: . A - the matrix to check
8993: Output Parameters:
8994: + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
8995: - flg - the result (only valid if set is `PETSC_TRUE`)
8997: Level: advanced
8999: Notes:
9000: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9002: One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9003: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9005: .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9006: @*/
9007: PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9008: {
9012: if (A->spd != PETSC_BOOL3_UNKNOWN) {
9013: *set = PETSC_TRUE;
9014: *flg = PetscBool3ToBool(A->spd);
9015: } else {
9016: *set = PETSC_FALSE;
9017: }
9018: return 0;
9019: }
9021: /*@
9022: MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9024: Not Collective
9026: Input Parameter:
9027: . A - the matrix to check
9029: Output Parameters:
9030: + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9031: - flg - the result (only valid if set is `PETSC_TRUE`)
9033: Level: advanced
9035: Notes:
9036: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9037: if you want it explicitly checked
9039: One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9040: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9042: .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9043: @*/
9044: PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9045: {
9049: if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9050: *set = PETSC_TRUE;
9051: *flg = PetscBool3ToBool(A->hermitian);
9052: } else {
9053: *set = PETSC_FALSE;
9054: }
9055: return 0;
9056: }
9058: /*@
9059: MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9061: Collective on Mat
9063: Input Parameter:
9064: . A - the matrix to test
9066: Output Parameters:
9067: . flg - the result
9069: Notes:
9070: If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9072: 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
9073: symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9075: Level: intermediate
9077: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9078: @*/
9079: PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9080: {
9083: if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9084: *flg = PetscBool3ToBool(A->structurally_symmetric);
9085: } else {
9086: PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9087: MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg);
9088: }
9089: return 0;
9090: }
9092: /*@
9093: MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9095: Not Collective
9097: Input Parameter:
9098: . A - the matrix to check
9100: Output Parameters:
9101: + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9102: - flg - the result (only valid if set is PETSC_TRUE)
9104: Level: advanced
9106: Notes:
9107: 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
9108: symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9110: Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9112: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9113: @*/
9114: PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9115: {
9119: if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9120: *set = PETSC_TRUE;
9121: *flg = PetscBool3ToBool(A->structurally_symmetric);
9122: } else {
9123: *set = PETSC_FALSE;
9124: }
9125: return 0;
9126: }
9128: /*@
9129: MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9130: to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9132: Not collective
9134: Input Parameter:
9135: . mat - the matrix
9137: Output Parameters:
9138: + nstash - the size of the stash
9139: . reallocs - the number of additional mallocs incurred.
9140: . bnstash - the size of the block stash
9141: - breallocs - the number of additional mallocs incurred.in the block stash
9143: Level: advanced
9145: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9146: @*/
9147: PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9148: {
9149: MatStashGetInfo_Private(&mat->stash, nstash, reallocs);
9150: MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs);
9151: return 0;
9152: }
9154: /*@C
9155: MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9156: parallel layout, `PetscLayout` for rows and columns
9158: Collective
9160: Input Parameter:
9161: . mat - the matrix
9163: Output Parameters:
9164: + right - (optional) vector that the matrix can be multiplied against
9165: - left - (optional) vector that the matrix vector product can be stored in
9167: Notes:
9168: 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()`.
9170: These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9172: Level: advanced
9174: .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9175: @*/
9176: PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9177: {
9180: if (mat->ops->getvecs) {
9181: PetscUseTypeMethod(mat, getvecs, right, left);
9182: } else {
9183: PetscInt rbs, cbs;
9184: MatGetBlockSizes(mat, &rbs, &cbs);
9185: if (right) {
9187: VecCreate(PetscObjectComm((PetscObject)mat), right);
9188: VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE);
9189: VecSetBlockSize(*right, cbs);
9190: VecSetType(*right, mat->defaultvectype);
9191: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9192: if (mat->boundtocpu && mat->bindingpropagates) {
9193: VecSetBindingPropagates(*right, PETSC_TRUE);
9194: VecBindToCPU(*right, PETSC_TRUE);
9195: }
9196: #endif
9197: PetscLayoutReference(mat->cmap, &(*right)->map);
9198: }
9199: if (left) {
9201: VecCreate(PetscObjectComm((PetscObject)mat), left);
9202: VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE);
9203: VecSetBlockSize(*left, rbs);
9204: VecSetType(*left, mat->defaultvectype);
9205: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9206: if (mat->boundtocpu && mat->bindingpropagates) {
9207: VecSetBindingPropagates(*left, PETSC_TRUE);
9208: VecBindToCPU(*left, PETSC_TRUE);
9209: }
9210: #endif
9211: PetscLayoutReference(mat->rmap, &(*left)->map);
9212: }
9213: }
9214: return 0;
9215: }
9217: /*@C
9218: MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9219: with default values.
9221: Not Collective
9223: Input Parameters:
9224: . info - the `MatFactorInfo` data structure
9226: Notes:
9227: The solvers are generally used through the `KSP` and `PC` objects, for example
9228: `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9230: Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9232: Level: developer
9234: Developer Note:
9235: The Fortran interface is not autogenerated as the
9236: interface definition cannot be generated correctly [due to `MatFactorInfo`]
9238: .seealso: `MatGetFactor()`, `MatFactorInfo`
9239: @*/
9240: PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9241: {
9242: PetscMemzero(info, sizeof(MatFactorInfo));
9243: return 0;
9244: }
9246: /*@
9247: MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9249: Collective
9251: Input Parameters:
9252: + mat - the factored matrix
9253: - is - the index set defining the Schur indices (0-based)
9255: Notes:
9256: Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9258: You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9260: This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9262: Level: advanced
9264: .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9265: `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9267: @*/
9268: PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9269: {
9270: PetscErrorCode (*f)(Mat, IS);
9278: PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f);
9280: MatDestroy(&mat->schur);
9281: (*f)(mat, is);
9283: return 0;
9284: }
9286: /*@
9287: MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9289: Logically Collective
9291: Input Parameters:
9292: + F - the factored matrix obtained by calling `MatGetFactor()`
9293: . S - location where to return the Schur complement, can be NULL
9294: - status - the status of the Schur complement matrix, can be NULL
9296: Notes:
9297: You must call `MatFactorSetSchurIS()` before calling this routine.
9299: This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9301: The routine provides a copy of the Schur matrix stored within the solver data structures.
9302: The caller must destroy the object when it is no longer needed.
9303: If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9305: 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)
9307: See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9309: Developer Note:
9310: The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9311: matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9313: Level: advanced
9315: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9316: @*/
9317: PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9318: {
9322: if (S) {
9323: PetscErrorCode (*f)(Mat, Mat *);
9325: PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f);
9326: if (f) {
9327: (*f)(F, S);
9328: } else {
9329: MatDuplicate(F->schur, MAT_COPY_VALUES, S);
9330: }
9331: }
9332: if (status) *status = F->schur_status;
9333: return 0;
9334: }
9336: /*@
9337: MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9339: Logically Collective
9341: Input Parameters:
9342: + F - the factored matrix obtained by calling `MatGetFactor()`
9343: . *S - location where to return the Schur complement, can be NULL
9344: - status - the status of the Schur complement matrix, can be NULL
9346: Notes:
9347: You must call `MatFactorSetSchurIS()` before calling this routine.
9349: Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9351: The routine returns a the Schur Complement stored within the data strutures of the solver.
9353: If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9355: The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9357: Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9359: See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9361: Level: advanced
9363: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9364: @*/
9365: PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9366: {
9370: if (S) *S = F->schur;
9371: if (status) *status = F->schur_status;
9372: return 0;
9373: }
9375: /*@
9376: MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9378: Logically Collective
9380: Input Parameters:
9381: + F - the factored matrix obtained by calling `MatGetFactor()`
9382: . *S - location where the Schur complement is stored
9383: - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9385: Level: advanced
9387: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9388: @*/
9389: PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9390: {
9392: if (S) {
9394: *S = NULL;
9395: }
9396: F->schur_status = status;
9397: MatFactorUpdateSchurStatus_Private(F);
9398: return 0;
9399: }
9401: /*@
9402: MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9404: Logically Collective
9406: Input Parameters:
9407: + F - the factored matrix obtained by calling `MatGetFactor()`
9408: . rhs - location where the right hand side of the Schur complement system is stored
9409: - sol - location where the solution of the Schur complement system has to be returned
9411: Notes:
9412: The sizes of the vectors should match the size of the Schur complement
9414: Must be called after `MatFactorSetSchurIS()`
9416: Level: advanced
9418: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9419: @*/
9420: PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9421: {
9430: MatFactorFactorizeSchurComplement(F);
9431: switch (F->schur_status) {
9432: case MAT_FACTOR_SCHUR_FACTORED:
9433: MatSolveTranspose(F->schur, rhs, sol);
9434: break;
9435: case MAT_FACTOR_SCHUR_INVERTED:
9436: MatMultTranspose(F->schur, rhs, sol);
9437: break;
9438: default:
9439: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9440: }
9441: return 0;
9442: }
9444: /*@
9445: MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9447: Logically Collective
9449: Input Parameters:
9450: + F - the factored matrix obtained by calling `MatGetFactor()`
9451: . rhs - location where the right hand side of the Schur complement system is stored
9452: - sol - location where the solution of the Schur complement system has to be returned
9454: Notes:
9455: The sizes of the vectors should match the size of the Schur complement
9457: Must be called after `MatFactorSetSchurIS()`
9459: Level: advanced
9461: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9462: @*/
9463: PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9464: {
9473: MatFactorFactorizeSchurComplement(F);
9474: switch (F->schur_status) {
9475: case MAT_FACTOR_SCHUR_FACTORED:
9476: MatSolve(F->schur, rhs, sol);
9477: break;
9478: case MAT_FACTOR_SCHUR_INVERTED:
9479: MatMult(F->schur, rhs, sol);
9480: break;
9481: default:
9482: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9483: }
9484: return 0;
9485: }
9487: /*@
9488: MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9490: Logically Collective on F
9492: Input Parameters:
9493: . F - the factored matrix obtained by calling `MatGetFactor()`
9495: Notes:
9496: Must be called after `MatFactorSetSchurIS()`.
9498: Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9500: Level: advanced
9502: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9503: @*/
9504: PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9505: {
9508: if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) return 0;
9509: MatFactorFactorizeSchurComplement(F);
9510: MatFactorInvertSchurComplement_Private(F);
9511: F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9512: return 0;
9513: }
9515: /*@
9516: MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9518: Logically Collective
9520: Input Parameters:
9521: . F - the factored matrix obtained by calling `MatGetFactor()`
9523: Note:
9524: Must be called after `MatFactorSetSchurIS()`
9526: Level: advanced
9528: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9529: @*/
9530: PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9531: {
9534: if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) return 0;
9535: MatFactorFactorizeSchurComplement_Private(F);
9536: F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9537: return 0;
9538: }
9540: /*@
9541: MatPtAP - Creates the matrix product C = P^T * A * P
9543: Neighbor-wise Collective on A
9545: Input Parameters:
9546: + A - the matrix
9547: . P - the projection matrix
9548: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9549: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9550: if the result is a dense matrix this is irrelevant
9552: Output Parameters:
9553: . C - the product matrix
9555: Notes:
9556: C will be created and must be destroyed by the user with `MatDestroy()`.
9558: An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9560: Developer Note:
9561: For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9563: Level: intermediate
9565: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9566: @*/
9567: PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9568: {
9569: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9572: if (scall == MAT_INITIAL_MATRIX) {
9573: MatProductCreate(A, P, NULL, C);
9574: MatProductSetType(*C, MATPRODUCT_PtAP);
9575: MatProductSetAlgorithm(*C, "default");
9576: MatProductSetFill(*C, fill);
9578: (*C)->product->api_user = PETSC_TRUE;
9579: MatProductSetFromOptions(*C);
9581: MatProductSymbolic(*C);
9582: } else { /* scall == MAT_REUSE_MATRIX */
9583: MatProductReplaceMats(A, P, NULL, *C);
9584: }
9586: MatProductNumeric(*C);
9587: (*C)->symmetric = A->symmetric;
9588: (*C)->spd = A->spd;
9589: return 0;
9590: }
9592: /*@
9593: MatRARt - Creates the matrix product C = R * A * R^T
9595: Neighbor-wise Collective on A
9597: Input Parameters:
9598: + A - the matrix
9599: . R - the projection matrix
9600: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9601: - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9602: if the result is a dense matrix this is irrelevant
9604: Output Parameters:
9605: . C - the product matrix
9607: Notes:
9608: C will be created and must be destroyed by the user with `MatDestroy()`.
9610: An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9612: This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9613: which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9614: parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9615: We recommend using MatPtAP().
9617: Level: intermediate
9619: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9620: @*/
9621: PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9622: {
9623: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9626: if (scall == MAT_INITIAL_MATRIX) {
9627: MatProductCreate(A, R, NULL, C);
9628: MatProductSetType(*C, MATPRODUCT_RARt);
9629: MatProductSetAlgorithm(*C, "default");
9630: MatProductSetFill(*C, fill);
9632: (*C)->product->api_user = PETSC_TRUE;
9633: MatProductSetFromOptions(*C);
9635: MatProductSymbolic(*C);
9636: } else { /* scall == MAT_REUSE_MATRIX */
9637: MatProductReplaceMats(A, R, NULL, *C);
9638: }
9640: MatProductNumeric(*C);
9641: if (A->symmetric == PETSC_BOOL3_TRUE) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9642: return 0;
9643: }
9645: static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9646: {
9649: if (scall == MAT_INITIAL_MATRIX) {
9650: PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]);
9651: MatProductCreate(A, B, NULL, C);
9652: MatProductSetType(*C, ptype);
9653: MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT);
9654: MatProductSetFill(*C, fill);
9656: (*C)->product->api_user = PETSC_TRUE;
9657: MatProductSetFromOptions(*C);
9658: MatProductSymbolic(*C);
9659: } else { /* scall == MAT_REUSE_MATRIX */
9660: Mat_Product *product = (*C)->product;
9661: PetscBool isdense;
9663: PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "");
9664: if (isdense && product && product->type != ptype) {
9665: MatProductClear(*C);
9666: product = NULL;
9667: }
9668: PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]);
9669: if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9670: if (isdense) {
9671: MatProductCreate_Private(A, B, NULL, *C);
9672: product = (*C)->product;
9673: product->fill = fill;
9674: product->api_user = PETSC_TRUE;
9675: product->clear = PETSC_TRUE;
9677: MatProductSetType(*C, ptype);
9678: MatProductSetFromOptions(*C);
9680: MatProductSymbolic(*C);
9681: } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9682: } else { /* user may change input matrices A or B when REUSE */
9683: MatProductReplaceMats(A, B, NULL, *C);
9684: }
9685: }
9686: MatProductNumeric(*C);
9687: return 0;
9688: }
9690: /*@
9691: MatMatMult - Performs matrix-matrix multiplication C=A*B.
9693: Neighbor-wise Collective on A
9695: Input Parameters:
9696: + A - the left matrix
9697: . B - the right matrix
9698: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9699: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9700: if the result is a dense matrix this is irrelevant
9702: Output Parameters:
9703: . C - the product matrix
9705: Notes:
9706: Unless scall is `MAT_REUSE_MATRIX` C will be created.
9708: `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
9709: call to this function with `MAT_INITIAL_MATRIX`.
9711: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9713: 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`,
9714: rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9716: Example of Usage:
9717: .vb
9718: MatProductCreate(A,B,NULL,&C);
9719: MatProductSetType(C,MATPRODUCT_AB);
9720: MatProductSymbolic(C);
9721: MatProductNumeric(C); // compute C=A * B
9722: MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9723: MatProductNumeric(C);
9724: MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9725: MatProductNumeric(C);
9726: .ve
9728: Level: intermediate
9730: .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9731: @*/
9732: PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9733: {
9734: MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C);
9735: return 0;
9736: }
9738: /*@
9739: MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9741: Neighbor-wise Collective on A
9743: Input Parameters:
9744: + A - the left matrix
9745: . B - the right matrix
9746: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9747: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9749: Output Parameters:
9750: . C - the product matrix
9752: Notes:
9753: C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9755: `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9757: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9758: actually needed.
9760: This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9761: and for pairs of `MATMPIDENSE` matrices.
9763: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
9765: Options Database Keys:
9766: . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9767: first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9768: the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9770: Level: intermediate
9772: .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9773: @*/
9774: PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9775: {
9776: MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C);
9777: if (A == B) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9778: return 0;
9779: }
9781: /*@
9782: MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
9784: Neighbor-wise Collective on A
9786: Input Parameters:
9787: + A - the left matrix
9788: . B - the right matrix
9789: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9790: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9792: Output Parameters:
9793: . C - the product matrix
9795: Notes:
9796: C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9798: `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9800: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
9802: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9803: actually needed.
9805: This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9806: which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices.
9808: Level: intermediate
9810: .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9811: @*/
9812: PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9813: {
9814: MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C);
9815: return 0;
9816: }
9818: /*@
9819: MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
9821: Neighbor-wise Collective on A
9823: Input Parameters:
9824: + A - the left matrix
9825: . B - the middle matrix
9826: . C - the right matrix
9827: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9828: - 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
9829: if the result is a dense matrix this is irrelevant
9831: Output Parameters:
9832: . D - the product matrix
9834: Notes:
9835: Unless scall is `MAT_REUSE_MATRIX` D will be created.
9837: `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9839: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
9841: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9842: actually needed.
9844: If you have many matrices with the same non-zero structure to multiply, you
9845: should use `MAT_REUSE_MATRIX` in all calls but the first
9847: Level: intermediate
9849: .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9850: @*/
9851: PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
9852: {
9853: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
9856: if (scall == MAT_INITIAL_MATRIX) {
9857: MatProductCreate(A, B, C, D);
9858: MatProductSetType(*D, MATPRODUCT_ABC);
9859: MatProductSetAlgorithm(*D, "default");
9860: MatProductSetFill(*D, fill);
9862: (*D)->product->api_user = PETSC_TRUE;
9863: MatProductSetFromOptions(*D);
9865: ((PetscObject)C)->type_name);
9866: MatProductSymbolic(*D);
9867: } else { /* user may change input matrices when REUSE */
9868: MatProductReplaceMats(A, B, C, *D);
9869: }
9870: MatProductNumeric(*D);
9871: return 0;
9872: }
9874: /*@
9875: MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9877: Collective
9879: Input Parameters:
9880: + mat - the matrix
9881: . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9882: . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
9883: - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9885: Output Parameter:
9886: . matredundant - redundant matrix
9888: Notes:
9889: `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
9890: original matrix has not changed from that last call to MatCreateRedundantMatrix().
9892: This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9893: calling it.
9895: `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
9897: Level: advanced
9899: .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
9900: @*/
9901: PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
9902: {
9903: MPI_Comm comm;
9904: PetscMPIInt size;
9905: PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9906: Mat_Redundant *redund = NULL;
9907: PetscSubcomm psubcomm = NULL;
9908: MPI_Comm subcomm_in = subcomm;
9909: Mat *matseq;
9910: IS isrow, iscol;
9911: PetscBool newsubcomm = PETSC_FALSE;
9914: if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9917: }
9919: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
9920: if (size == 1 || nsubcomm == 1) {
9921: if (reuse == MAT_INITIAL_MATRIX) {
9922: MatDuplicate(mat, MAT_COPY_VALUES, matredundant);
9923: } else {
9925: MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN);
9926: }
9927: return 0;
9928: }
9932: MatCheckPreallocated(mat, 1);
9934: PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0);
9935: if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9936: /* create psubcomm, then get subcomm */
9937: PetscObjectGetComm((PetscObject)mat, &comm);
9938: MPI_Comm_size(comm, &size);
9941: PetscSubcommCreate(comm, &psubcomm);
9942: PetscSubcommSetNumber(psubcomm, nsubcomm);
9943: PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS);
9944: PetscSubcommSetFromOptions(psubcomm);
9945: PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL);
9946: newsubcomm = PETSC_TRUE;
9947: PetscSubcommDestroy(&psubcomm);
9948: }
9950: /* get isrow, iscol and a local sequential matrix matseq[0] */
9951: if (reuse == MAT_INITIAL_MATRIX) {
9952: mloc_sub = PETSC_DECIDE;
9953: nloc_sub = PETSC_DECIDE;
9954: if (bs < 1) {
9955: PetscSplitOwnership(subcomm, &mloc_sub, &M);
9956: PetscSplitOwnership(subcomm, &nloc_sub, &N);
9957: } else {
9958: PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M);
9959: PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N);
9960: }
9961: MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm);
9962: rstart = rend - mloc_sub;
9963: ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow);
9964: ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol);
9965: } else { /* reuse == MAT_REUSE_MATRIX */
9967: /* retrieve subcomm */
9968: PetscObjectGetComm((PetscObject)(*matredundant), &subcomm);
9969: redund = (*matredundant)->redundant;
9970: isrow = redund->isrow;
9971: iscol = redund->iscol;
9972: matseq = redund->matseq;
9973: }
9974: MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq);
9976: /* get matredundant over subcomm */
9977: if (reuse == MAT_INITIAL_MATRIX) {
9978: MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant);
9980: /* create a supporting struct and attach it to C for reuse */
9981: PetscNew(&redund);
9982: (*matredundant)->redundant = redund;
9983: redund->isrow = isrow;
9984: redund->iscol = iscol;
9985: redund->matseq = matseq;
9986: if (newsubcomm) {
9987: redund->subcomm = subcomm;
9988: } else {
9989: redund->subcomm = MPI_COMM_NULL;
9990: }
9991: } else {
9992: MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant);
9993: }
9994: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9995: if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
9996: MatBindToCPU(*matredundant, PETSC_TRUE);
9997: MatSetBindingPropagates(*matredundant, PETSC_TRUE);
9998: }
9999: #endif
10000: PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0);
10001: return 0;
10002: }
10004: /*@C
10005: MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10006: a given `Mat`. Each submatrix can span multiple procs.
10008: Collective
10010: Input Parameters:
10011: + mat - the matrix
10012: . subcomm - the subcommunicator obtained by MPI_Com_split(comm)
10013: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10015: Output Parameter:
10016: . subMat - 'parallel submatrices each spans a given subcomm
10018: Notes:
10019: The submatrix partition across processors is dictated by 'subComm' a
10020: communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
10021: is not restriced to be grouped with consecutive original ranks.
10023: Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10024: map directly to the layout of the original matrix [wrt the local
10025: row,col partitioning]. So the original 'DiagonalMat' naturally maps
10026: into the 'DiagonalMat' of the subMat, hence it is used directly from
10027: the subMat. However the offDiagMat looses some columns - and this is
10028: reconstructed with `MatSetValues()`
10030: This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10032: Level: advanced
10034: .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10035: @*/
10036: PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10037: {
10038: PetscMPIInt commsize, subCommSize;
10040: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize);
10041: MPI_Comm_size(subComm, &subCommSize);
10045: PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10046: PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10047: PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10048: return 0;
10049: }
10051: /*@
10052: MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10054: Not Collective
10056: Input Parameters:
10057: + mat - matrix to extract local submatrix from
10058: . isrow - local row indices for submatrix
10059: - iscol - local column indices for submatrix
10061: Output Parameter:
10062: . submat - the submatrix
10064: Level: intermediate
10066: Notes:
10067: The submat should be returned with `MatRestoreLocalSubMatrix()`.
10069: Depending on the format of mat, the returned submat may not implement `MatMult()`. Its communicator may be
10070: the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.
10072: The submat always implements `MatSetValuesLocal()`. If isrow and iscol have the same block size, then
10073: `MatSetValuesBlockedLocal()` will also be implemented.
10075: The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10076: Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10078: .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10079: @*/
10080: PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10081: {
10089: if (mat->ops->getlocalsubmatrix) {
10090: PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10091: } else {
10092: MatCreateLocalRef(mat, isrow, iscol, submat);
10093: }
10094: return 0;
10095: }
10097: /*@
10098: MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10100: Not Collective
10102: Input Parameters:
10103: + mat - matrix to extract local submatrix from
10104: . isrow - local row indices for submatrix
10105: . iscol - local column indices for submatrix
10106: - submat - the submatrix
10108: Level: intermediate
10110: .seealso: `MatGetLocalSubMatrix()`
10111: @*/
10112: PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10113: {
10121: if (mat->ops->restorelocalsubmatrix) {
10122: PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10123: } else {
10124: MatDestroy(submat);
10125: }
10126: *submat = NULL;
10127: return 0;
10128: }
10130: /* --------------------------------------------------------*/
10131: /*@
10132: MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10134: Collective
10136: Input Parameter:
10137: . mat - the matrix
10139: Output Parameter:
10140: . is - if any rows have zero diagonals this contains the list of them
10142: Level: developer
10144: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10145: @*/
10146: PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10147: {
10153: if (!mat->ops->findzerodiagonals) {
10154: Vec diag;
10155: const PetscScalar *a;
10156: PetscInt *rows;
10157: PetscInt rStart, rEnd, r, nrow = 0;
10159: MatCreateVecs(mat, &diag, NULL);
10160: MatGetDiagonal(mat, diag);
10161: MatGetOwnershipRange(mat, &rStart, &rEnd);
10162: VecGetArrayRead(diag, &a);
10163: for (r = 0; r < rEnd - rStart; ++r)
10164: if (a[r] == 0.0) ++nrow;
10165: PetscMalloc1(nrow, &rows);
10166: nrow = 0;
10167: for (r = 0; r < rEnd - rStart; ++r)
10168: if (a[r] == 0.0) rows[nrow++] = r + rStart;
10169: VecRestoreArrayRead(diag, &a);
10170: VecDestroy(&diag);
10171: ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is);
10172: } else {
10173: PetscUseTypeMethod(mat, findzerodiagonals, is);
10174: }
10175: return 0;
10176: }
10178: /*@
10179: MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10181: Collective
10183: Input Parameter:
10184: . mat - the matrix
10186: Output Parameter:
10187: . is - contains the list of rows with off block diagonal entries
10189: Level: developer
10191: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10192: @*/
10193: PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10194: {
10200: PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10201: return 0;
10202: }
10204: /*@C
10205: MatInvertBlockDiagonal - Inverts the block diagonal entries.
10207: Collective; No Fortran Support
10209: Input Parameters:
10210: . mat - the matrix
10212: Output Parameters:
10213: . values - the block inverses in column major order (FORTRAN-like)
10215: Level: advanced
10217: Notes:
10218: The size of the blocks is determined by the block size of the matrix.
10220: The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10222: The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10224: .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10225: @*/
10226: PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10227: {
10231: PetscUseTypeMethod(mat, invertblockdiagonal, values);
10232: return 0;
10233: }
10235: /*@C
10236: MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10238: Collective; No Fortran Support
10240: Input Parameters:
10241: + mat - the matrix
10242: . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10243: - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10245: Output Parameters:
10246: . values - the block inverses in column major order (FORTRAN-like)
10248: Level: advanced
10250: Notes:
10251: Use `MatInvertBlockDiagonal()` if all blocks have the same size
10253: The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10255: .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10256: @*/
10257: PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10258: {
10262: PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10263: return 0;
10264: }
10266: /*@
10267: MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10269: Collective on Mat
10271: Input Parameters:
10272: + A - the matrix
10273: - C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set.
10275: Note:
10276: The blocksize of the matrix is used to determine the blocks on the diagonal of C
10278: Level: advanced
10280: .seealso: `MatInvertBlockDiagonal()`
10281: @*/
10282: PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10283: {
10284: const PetscScalar *vals;
10285: PetscInt *dnnz;
10286: PetscInt m, rstart, rend, bs, i, j;
10288: MatInvertBlockDiagonal(A, &vals);
10289: MatGetBlockSize(A, &bs);
10290: MatGetLocalSize(A, &m, NULL);
10291: MatSetLayouts(C, A->rmap, A->cmap);
10292: PetscMalloc1(m / bs, &dnnz);
10293: for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10294: MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL);
10295: PetscFree(dnnz);
10296: MatGetOwnershipRange(C, &rstart, &rend);
10297: MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE);
10298: for (i = rstart / bs; i < rend / bs; i++) MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES);
10299: MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY);
10300: MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY);
10301: MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE);
10302: return 0;
10303: }
10305: /*@C
10306: MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10307: via `MatTransposeColoringCreate()`.
10309: Collective on c
10311: Input Parameter:
10312: . c - coloring context
10314: Level: intermediate
10316: .seealso: `MatTransposeColoringCreate()`
10317: @*/
10318: PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10319: {
10320: MatTransposeColoring matcolor = *c;
10322: if (!matcolor) return 0;
10323: if (--((PetscObject)matcolor)->refct > 0) {
10324: matcolor = NULL;
10325: return 0;
10326: }
10328: PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow);
10329: PetscFree(matcolor->rows);
10330: PetscFree(matcolor->den2sp);
10331: PetscFree(matcolor->colorforcol);
10332: PetscFree(matcolor->columns);
10333: if (matcolor->brows > 0) PetscFree(matcolor->lstart);
10334: PetscHeaderDestroy(c);
10335: return 0;
10336: }
10338: /*@C
10339: MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10340: a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10341: `MatTransposeColoring` to sparse B.
10343: Collective on coloring
10345: Input Parameters:
10346: + B - sparse matrix B
10347: . Btdense - symbolic dense matrix B^T
10348: - coloring - coloring context created with `MatTransposeColoringCreate()`
10350: Output Parameter:
10351: . Btdense - dense matrix B^T
10353: Level: developer
10355: Note:
10356: These are used internally for some implementations of `MatRARt()`
10358: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10360: @*/
10361: PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10362: {
10367: (B->ops->transcoloringapplysptoden)(coloring, B, Btdense);
10368: return 0;
10369: }
10371: /*@C
10372: MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10373: a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10374: in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10375: Csp from Cden.
10377: Collective
10379: Input Parameters:
10380: + coloring - coloring context created with `MatTransposeColoringCreate()`
10381: - Cden - matrix product of a sparse matrix and a dense matrix Btdense
10383: Output Parameter:
10384: . Csp - sparse matrix
10386: Level: developer
10388: Note:
10389: These are used internally for some implementations of `MatRARt()`
10391: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10393: @*/
10394: PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10395: {
10400: (Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp);
10401: MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY);
10402: MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY);
10403: return 0;
10404: }
10406: /*@C
10407: MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10409: Collective
10411: Input Parameters:
10412: + mat - the matrix product C
10413: - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10415: Output Parameter:
10416: . color - the new coloring context
10418: Level: intermediate
10420: .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10421: `MatTransColoringApplyDenToSp()`
10422: @*/
10423: PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10424: {
10425: MatTransposeColoring c;
10426: MPI_Comm comm;
10428: PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10429: PetscObjectGetComm((PetscObject)mat, &comm);
10430: PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL);
10432: c->ctype = iscoloring->ctype;
10433: if (mat->ops->transposecoloringcreate) {
10434: PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10435: } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10437: *color = c;
10438: PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10439: return 0;
10440: }
10442: /*@
10443: MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10444: matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10445: same, otherwise it will be larger
10447: Not Collective
10449: Input Parameter:
10450: . A - the matrix
10452: Output Parameter:
10453: . state - the current state
10455: Notes:
10456: You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10457: different matrices
10459: Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10461: Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10463: Level: intermediate
10465: .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10466: @*/
10467: PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10468: {
10470: *state = mat->nonzerostate;
10471: return 0;
10472: }
10474: /*@
10475: MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10476: matrices from each processor
10478: Collective
10480: Input Parameters:
10481: + comm - the communicators the parallel matrix will live on
10482: . seqmat - the input sequential matrices
10483: . n - number of local columns (or `PETSC_DECIDE`)
10484: - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10486: Output Parameter:
10487: . mpimat - the parallel matrix generated
10489: Level: developer
10491: Note:
10492: The number of columns of the matrix in EACH processor MUST be the same.
10494: .seealso: `Mat`
10495: @*/
10496: PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10497: {
10498: PetscMPIInt size;
10500: MPI_Comm_size(comm, &size);
10501: if (size == 1) {
10502: if (reuse == MAT_INITIAL_MATRIX) {
10503: MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat);
10504: } else {
10505: MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN);
10506: }
10507: return 0;
10508: }
10512: PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0);
10513: (*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat);
10514: PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0);
10515: return 0;
10516: }
10518: /*@
10519: MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10521: Collective on A
10523: Input Parameters:
10524: + A - the matrix to create subdomains from
10525: - N - requested number of subdomains
10527: Output Parameters:
10528: + n - number of subdomains resulting on this rank
10529: - iss - `IS` list with indices of subdomains on this rank
10531: Level: advanced
10533: Note:
10534: The number of subdomains must be smaller than the communicator size
10536: .seealso: `Mat`, `IS`
10537: @*/
10538: PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10539: {
10540: MPI_Comm comm, subcomm;
10541: PetscMPIInt size, rank, color;
10542: PetscInt rstart, rend, k;
10544: PetscObjectGetComm((PetscObject)A, &comm);
10545: MPI_Comm_size(comm, &size);
10546: MPI_Comm_rank(comm, &rank);
10548: *n = 1;
10549: k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10550: color = rank / k;
10551: MPI_Comm_split(comm, color, rank, &subcomm);
10552: PetscMalloc1(1, iss);
10553: MatGetOwnershipRange(A, &rstart, &rend);
10554: ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]);
10555: MPI_Comm_free(&subcomm);
10556: return 0;
10557: }
10559: /*@
10560: MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10562: If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10563: If they are not the same, uses `MatMatMatMult()`.
10565: Once the coarse grid problem is constructed, correct for interpolation operators
10566: that are not of full rank, which can legitimately happen in the case of non-nested
10567: geometric multigrid.
10569: Input Parameters:
10570: + restrct - restriction operator
10571: . dA - fine grid matrix
10572: . interpolate - interpolation operator
10573: . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10574: - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10576: Output Parameters:
10577: . A - the Galerkin coarse matrix
10579: Options Database Key:
10580: . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10582: Level: developer
10584: .seealso: `MatPtAP()`, `MatMatMatMult()`
10585: @*/
10586: PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10587: {
10588: IS zerorows;
10589: Vec diag;
10592: /* Construct the coarse grid matrix */
10593: if (interpolate == restrct) {
10594: MatPtAP(dA, interpolate, reuse, fill, A);
10595: } else {
10596: MatMatMatMult(restrct, dA, interpolate, reuse, fill, A);
10597: }
10599: /* If the interpolation matrix is not of full rank, A will have zero rows.
10600: This can legitimately happen in the case of non-nested geometric multigrid.
10601: In that event, we set the rows of the matrix to the rows of the identity,
10602: ignoring the equations (as the RHS will also be zero). */
10604: MatFindZeroRows(*A, &zerorows);
10606: if (zerorows != NULL) { /* if there are any zero rows */
10607: MatCreateVecs(*A, &diag, NULL);
10608: MatGetDiagonal(*A, diag);
10609: VecISSet(diag, zerorows, 1.0);
10610: MatDiagonalSet(*A, diag, INSERT_VALUES);
10611: VecDestroy(&diag);
10612: ISDestroy(&zerorows);
10613: }
10614: return 0;
10615: }
10617: /*@C
10618: MatSetOperation - Allows user to set a matrix operation for any matrix type
10620: Logically Collective
10622: Input Parameters:
10623: + mat - the matrix
10624: . op - the name of the operation
10625: - f - the function that provides the operation
10627: Level: developer
10629: Usage:
10630: $ extern PetscErrorCode usermult(Mat,Vec,Vec);
10631: $ MatCreateXXX(comm,...&A;
10632: $ MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult;
10634: Notes:
10635: See the file include/petscmat.h for a complete list of matrix
10636: operations, which all have the form MATOP_<OPERATION>, where
10637: <OPERATION> is the name (in all capital letters) of the
10638: user interface routine (e.g., MatMult() -> MATOP_MULT).
10640: All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10641: sequence as the usual matrix interface routines, since they
10642: are intended to be accessed via the usual matrix interface
10643: routines, e.g.,
10644: $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10646: In particular each function MUST return an error code of 0 on success and
10647: nonzero on failure.
10649: This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10651: .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10652: @*/
10653: PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10654: {
10656: if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10657: (((void (**)(void))mat->ops)[op]) = f;
10658: return 0;
10659: }
10661: /*@C
10662: MatGetOperation - Gets a matrix operation for any matrix type.
10664: Not Collective
10666: Input Parameters:
10667: + mat - the matrix
10668: - op - the name of the operation
10670: Output Parameter:
10671: . f - the function that provides the operation
10673: Level: developer
10675: Usage:
10676: $ PetscErrorCode (*usermult)(Mat,Vec,Vec);
10677: $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10679: Notes:
10680: See the file include/petscmat.h for a complete list of matrix
10681: operations, which all have the form MATOP_<OPERATION>, where
10682: <OPERATION> is the name (in all capital letters) of the
10683: user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10685: This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10687: .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10688: @*/
10689: PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10690: {
10692: *f = (((void (**)(void))mat->ops)[op]);
10693: return 0;
10694: }
10696: /*@
10697: MatHasOperation - Determines whether the given matrix supports the particular operation.
10699: Not Collective
10701: Input Parameters:
10702: + mat - the matrix
10703: - op - the operation, for example, `MATOP_GET_DIAGONAL`
10705: Output Parameter:
10706: . has - either `PETSC_TRUE` or `PETSC_FALSE`
10708: Level: advanced
10710: Note:
10711: See the file include/petscmat.h for a complete list of matrix
10712: operations, which all have the form MATOP_<OPERATION>, where
10713: <OPERATION> is the name (in all capital letters) of the
10714: user-level routine. E.g., `MatNorm()` -> `MATOP_NORM`.
10716: .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10717: @*/
10718: PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10719: {
10722: if (mat->ops->hasoperation) {
10723: PetscUseTypeMethod(mat, hasoperation, op, has);
10724: } else {
10725: if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10726: else {
10727: *has = PETSC_FALSE;
10728: if (op == MATOP_CREATE_SUBMATRIX) {
10729: PetscMPIInt size;
10731: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
10732: if (size == 1) MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has);
10733: }
10734: }
10735: }
10736: return 0;
10737: }
10739: /*@
10740: MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
10742: Collective
10744: Input Parameters:
10745: . mat - the matrix
10747: Output Parameter:
10748: . cong - either `PETSC_TRUE` or `PETSC_FALSE`
10750: Level: beginner
10752: .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10753: @*/
10754: PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10755: {
10759: if (!mat->rmap || !mat->cmap) {
10760: *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10761: return 0;
10762: }
10763: if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10764: PetscLayoutSetUp(mat->rmap);
10765: PetscLayoutSetUp(mat->cmap);
10766: PetscLayoutCompare(mat->rmap, mat->cmap, cong);
10767: if (*cong) mat->congruentlayouts = 1;
10768: else mat->congruentlayouts = 0;
10769: } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10770: return 0;
10771: }
10773: PetscErrorCode MatSetInf(Mat A)
10774: {
10775: PetscUseTypeMethod(A, setinf);
10776: return 0;
10777: }
10779: /*C
10780: 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
10781: and possibly removes small values from the graph structure.
10783: Collective
10785: Input Parameters:
10786: + A - the matrix
10787: . sym - `PETSC_TRUE` indicates that the graph should be symmetrized
10788: . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
10789: - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
10791: Output Parameter:
10792: . graph - the resulting graph
10794: Level: advanced
10796: .seealso: `MatCreate()`, `PCGAMG`
10797: */
10798: PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
10799: {
10803: PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
10804: return 0;
10805: }