Actual source code: matrix.c
1: /*
2: This is where the abstract matrix operations are defined
3: Portions of this code are under:
4: Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5: */
7: #include <petsc/private/matimpl.h>
8: #include <petsc/private/isimpl.h>
9: #include <petsc/private/vecimpl.h>
11: /* Logging support */
12: PetscClassId MAT_CLASSID;
13: PetscClassId MAT_COLORING_CLASSID;
14: PetscClassId MAT_FDCOLORING_CLASSID;
15: PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
17: PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
18: PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19: PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20: PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21: PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22: PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23: PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24: PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25: PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26: PetscLogEvent MAT_TransposeColoringCreate;
27: PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28: PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29: PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30: PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31: PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32: PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33: PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34: PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35: PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
36: PetscLogEvent MAT_GetMultiProcBlock;
37: PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
38: PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
39: PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
40: PetscLogEvent MAT_SetValuesBatch;
41: PetscLogEvent MAT_ViennaCLCopyToGPU;
42: PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43: PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44: PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45: PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46: PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
48: const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
50: /*@
51: MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
52: for sparse matrices that already have locations it fills the locations with random numbers
54: Logically Collective on mat
56: Input Parameters:
57: + x - the matrix
58: - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and
59: it will create one internally.
61: Output Parameter:
62: . x - the matrix
64: Example of Usage:
65: .vb
66: PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
67: MatSetRandom(x,rctx);
68: PetscRandomDestroy(rctx);
69: .ve
71: Level: intermediate
73: .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
74: @*/
75: PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
76: {
77: PetscRandom randObj = NULL;
82: MatCheckPreallocated(x, 1);
84: if (!rctx) {
85: MPI_Comm comm;
86: PetscObjectGetComm((PetscObject)x, &comm);
87: PetscRandomCreate(comm, &randObj);
88: PetscRandomSetType(randObj, x->defaultrandtype);
89: PetscRandomSetFromOptions(randObj);
90: rctx = randObj;
91: }
92: PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0);
93: PetscUseTypeMethod(x, setrandom, rctx);
94: PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0);
96: MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY);
97: MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY);
98: PetscRandomDestroy(&randObj);
99: return 0;
100: }
102: /*@
103: MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
105: Logically Collective on mat
107: Input Parameter:
108: . mat - the factored matrix
110: Output Parameters:
111: + pivot - the pivot value computed
112: - row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
113: the share the matrix
115: Level: advanced
117: Notes:
118: This routine does not work for factorizations done with external packages.
120: This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
122: This can be called on non-factored matrices that come from, for example, matrices used in SOR.
124: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
125: `MAT_FACTOR_NUMERIC_ZEROPIVOT`
126: @*/
127: PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
128: {
132: *pivot = mat->factorerror_zeropivot_value;
133: *row = mat->factorerror_zeropivot_row;
134: return 0;
135: }
137: /*@
138: MatFactorGetError - gets the error code from a factorization
140: Logically Collective on mat
142: Input Parameters:
143: . mat - the factored matrix
145: Output Parameter:
146: . err - the error code
148: Level: advanced
150: Note:
151: This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
153: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
154: `MatFactorError`
155: @*/
156: PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
157: {
160: *err = mat->factorerrortype;
161: return 0;
162: }
164: /*@
165: MatFactorClearError - clears the error code in a factorization
167: Logically Collective on mat
169: Input Parameter:
170: . mat - the factored matrix
172: Level: developer
174: Note:
175: This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
177: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
178: `MatGetErrorCode()`, `MatFactorError`
179: @*/
180: PetscErrorCode MatFactorClearError(Mat mat)
181: {
183: mat->factorerrortype = MAT_FACTOR_NOERROR;
184: mat->factorerror_zeropivot_value = 0.0;
185: mat->factorerror_zeropivot_row = 0;
186: return 0;
187: }
189: PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
190: {
191: Vec r, l;
192: const PetscScalar *al;
193: PetscInt i, nz, gnz, N, n;
195: MatCreateVecs(mat, &r, &l);
196: if (!cols) { /* nonzero rows */
197: MatGetSize(mat, &N, NULL);
198: MatGetLocalSize(mat, &n, NULL);
199: VecSet(l, 0.0);
200: VecSetRandom(r, NULL);
201: MatMult(mat, r, l);
202: VecGetArrayRead(l, &al);
203: } else { /* nonzero columns */
204: MatGetSize(mat, NULL, &N);
205: MatGetLocalSize(mat, NULL, &n);
206: VecSet(r, 0.0);
207: VecSetRandom(l, NULL);
208: MatMultTranspose(mat, l, r);
209: VecGetArrayRead(r, &al);
210: }
211: if (tol <= 0.0) {
212: for (i = 0, nz = 0; i < n; i++)
213: if (al[i] != 0.0) nz++;
214: } else {
215: for (i = 0, nz = 0; i < n; i++)
216: if (PetscAbsScalar(al[i]) > tol) nz++;
217: }
218: MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
219: if (gnz != N) {
220: PetscInt *nzr;
221: PetscMalloc1(nz, &nzr);
222: if (nz) {
223: if (tol < 0) {
224: for (i = 0, nz = 0; i < n; i++)
225: if (al[i] != 0.0) nzr[nz++] = i;
226: } else {
227: for (i = 0, nz = 0; i < n; i++)
228: if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
229: }
230: }
231: ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero);
232: } else *nonzero = NULL;
233: if (!cols) { /* nonzero rows */
234: VecRestoreArrayRead(l, &al);
235: } else {
236: VecRestoreArrayRead(r, &al);
237: }
238: VecDestroy(&l);
239: VecDestroy(&r);
240: return 0;
241: }
243: /*@
244: MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
246: Input Parameter:
247: . A - the matrix
249: Output Parameter:
250: . keptrows - the rows that are not completely zero
252: Note:
253: keptrows is set to NULL if all rows are nonzero.
255: Level: intermediate
257: .seealso: `Mat`, `MatFindZeroRows()`
258: @*/
259: PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
260: {
266: if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
267: else MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows);
268: return 0;
269: }
271: /*@
272: MatFindZeroRows - Locate all rows that are completely zero in the matrix
274: Input Parameter:
275: . A - the matrix
277: Output Parameter:
278: . zerorows - the rows that are completely zero
280: Note:
281: zerorows is set to NULL if no rows are zero.
283: Level: intermediate
285: .seealso: `Mat`, `MatFindNonzeroRows()`
286: @*/
287: PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
288: {
289: IS keptrows;
290: PetscInt m, n;
295: MatFindNonzeroRows(mat, &keptrows);
296: /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
297: In keeping with this convention, we set zerorows to NULL if there are no zero
298: rows. */
299: if (keptrows == NULL) {
300: *zerorows = NULL;
301: } else {
302: MatGetOwnershipRange(mat, &m, &n);
303: ISComplement(keptrows, m, n, zerorows);
304: ISDestroy(&keptrows);
305: }
306: return 0;
307: }
309: /*@
310: MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
312: Not Collective
314: Input Parameters:
315: . A - the matrix
317: Output Parameters:
318: . a - the diagonal part (which is a SEQUENTIAL matrix)
320: Notes:
321: See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
323: Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation.
325: Level: advanced
327: .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
328: @*/
329: PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
330: {
335: if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
336: else {
337: PetscMPIInt size;
339: MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);
341: *a = A;
342: }
343: return 0;
344: }
346: /*@
347: MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
349: Collective on mat
351: Input Parameters:
352: . mat - the matrix
354: Output Parameter:
355: . trace - the sum of the diagonal entries
357: Level: advanced
359: .seealso: `Mat`
360: @*/
361: PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
362: {
363: Vec diag;
367: MatCreateVecs(mat, &diag, NULL);
368: MatGetDiagonal(mat, diag);
369: VecSum(diag, trace);
370: VecDestroy(&diag);
371: return 0;
372: }
374: /*@
375: MatRealPart - Zeros out the imaginary part of the matrix
377: Logically Collective on mat
379: Input Parameters:
380: . mat - the matrix
382: Level: advanced
384: .seealso: `MatImaginaryPart()`
385: @*/
386: PetscErrorCode MatRealPart(Mat mat)
387: {
392: MatCheckPreallocated(mat, 1);
393: PetscUseTypeMethod(mat, realpart);
394: return 0;
395: }
397: /*@C
398: MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
400: Collective on mat
402: Input Parameter:
403: . mat - the matrix
405: Output Parameters:
406: + nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
407: - ghosts - the global indices of the ghost points
409: Note:
410: the nghosts and ghosts are suitable to pass into `VecCreateGhost()`
412: Level: advanced
414: .seealso: `Mat`, `VecCreateGhost()`
415: @*/
416: PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
417: {
422: if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
423: else {
424: if (nghosts) *nghosts = 0;
425: if (ghosts) *ghosts = NULL;
426: }
427: return 0;
428: }
430: /*@
431: MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
433: Logically Collective on mat
435: Input Parameters:
436: . mat - the matrix
438: Level: advanced
440: .seealso: `MatRealPart()`
441: @*/
442: PetscErrorCode MatImaginaryPart(Mat mat)
443: {
448: MatCheckPreallocated(mat, 1);
449: PetscUseTypeMethod(mat, imaginarypart);
450: return 0;
451: }
453: /*@
454: MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
456: Not Collective
458: Input Parameter:
459: . mat - the matrix
461: Output Parameters:
462: + missing - is any diagonal missing
463: - dd - first diagonal entry that is missing (optional) on this process
465: Level: advanced
467: .seealso: `Mat`
468: @*/
469: PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
470: {
476: PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
477: return 0;
478: }
480: /*@C
481: MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()`
482: for each row that you get to ensure that your application does
483: not bleed memory.
485: Not Collective
487: Input Parameters:
488: + mat - the matrix
489: - row - the row to get
491: Output Parameters:
492: + ncols - if not NULL, the number of nonzeros in the row
493: . cols - if not NULL, the column numbers
494: - vals - if not NULL, the values
496: Notes:
497: This routine is provided for people who need to have direct access
498: to the structure of a matrix. We hope that we provide enough
499: high-level matrix routines that few users will need it.
501: `MatGetRow()` always returns 0-based column indices, regardless of
502: whether the internal representation is 0-based (default) or 1-based.
504: For better efficiency, set cols and/or vals to NULL if you do
505: not wish to extract these quantities.
507: The user can only examine the values extracted with `MatGetRow()`;
508: the values cannot be altered. To change the matrix entries, one
509: must use `MatSetValues()`.
511: You can only have one call to `MatGetRow()` outstanding for a particular
512: matrix at a time, per processor. `MatGetRow()` can only obtain rows
513: associated with the given processor, it cannot get rows from the
514: other processors; for that we suggest using `MatCreateSubMatrices()`, then
515: MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
516: is in the global number of rows.
518: Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
520: Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
522: Fortran Note:
523: The calling sequence from Fortran is
524: .vb
525: MatGetRow(matrix,row,ncols,cols,values,ierr)
526: Mat matrix (input)
527: integer row (input)
528: integer ncols (output)
529: integer cols(maxcols) (output)
530: double precision (or double complex) values(maxcols) output
531: .ve
532: where maxcols >= maximum nonzeros in any row of the matrix.
534: Caution:
535: Do not try to change the contents of the output arrays (cols and vals).
536: In some cases, this may corrupt the matrix.
538: Level: advanced
540: .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
541: @*/
542: PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
543: {
544: PetscInt incols;
550: MatCheckPreallocated(mat, 1);
552: PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0);
553: (*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
554: if (ncols) *ncols = incols;
555: PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0);
556: return 0;
557: }
559: /*@
560: MatConjugate - replaces the matrix values with their complex conjugates
562: Logically Collective on mat
564: Input Parameters:
565: . mat - the matrix
567: Level: advanced
569: .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
570: @*/
571: PetscErrorCode MatConjugate(Mat mat)
572: {
575: if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
576: PetscUseTypeMethod(mat, conjugate);
577: PetscObjectStateIncrease((PetscObject)mat);
578: }
579: return 0;
580: }
582: /*@C
583: MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
585: Not Collective
587: Input Parameters:
588: + mat - the matrix
589: . row - the row to get
590: . ncols, cols - the number of nonzeros and their columns
591: - vals - if nonzero the column values
593: Notes:
594: This routine should be called after you have finished examining the entries.
596: This routine zeros out ncols, cols, and vals. This is to prevent accidental
597: us of the array after it has been restored. If you pass NULL, it will
598: not zero the pointers. Use of cols or vals after `MatRestoreRow()` is invalid.
600: Fortran Notes:
601: The calling sequence from Fortran is
602: .vb
603: MatRestoreRow(matrix,row,ncols,cols,values,ierr)
604: Mat matrix (input)
605: integer row (input)
606: integer ncols (output)
607: integer cols(maxcols) (output)
608: double precision (or double complex) values(maxcols) output
609: .ve
610: Where maxcols >= maximum nonzeros in any row of the matrix.
612: In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
613: before another call to `MatGetRow()` can be made.
615: Level: advanced
617: .seealso: `MatGetRow()`
618: @*/
619: PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
620: {
624: if (!mat->ops->restorerow) return 0;
625: (*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
626: if (ncols) *ncols = 0;
627: if (cols) *cols = NULL;
628: if (vals) *vals = NULL;
629: return 0;
630: }
632: /*@
633: MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
634: You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
636: Not Collective
638: Input Parameters:
639: . mat - the matrix
641: Note:
642: The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
644: Level: advanced
646: .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
647: @*/
648: PetscErrorCode MatGetRowUpperTriangular(Mat mat)
649: {
654: MatCheckPreallocated(mat, 1);
655: if (!mat->ops->getrowuppertriangular) return 0;
656: PetscUseTypeMethod(mat, getrowuppertriangular);
657: return 0;
658: }
660: /*@
661: MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
663: Not Collective
665: Input Parameters:
666: . mat - the matrix
668: Note:
669: This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
671: Level: advanced
673: .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()`
674: @*/
675: PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
676: {
681: MatCheckPreallocated(mat, 1);
682: if (!mat->ops->restorerowuppertriangular) return 0;
683: PetscUseTypeMethod(mat, restorerowuppertriangular);
684: return 0;
685: }
687: /*@C
688: MatSetOptionsPrefix - Sets the prefix used for searching for all
689: `Mat` options in the database.
691: Logically Collective on A
693: Input Parameters:
694: + A - the matrix
695: - prefix - the prefix to prepend to all option names
697: Notes:
698: A hyphen (-) must NOT be given at the beginning of the prefix name.
699: The first character of all runtime options is AUTOMATICALLY the hyphen.
701: This is NOT used for options for the factorization of the matrix. Normally the
702: prefix is automatically passed in from the PC calling the factorization. To set
703: it directly use `MatSetOptionsPrefixFactor()`
705: Level: advanced
707: .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
708: @*/
709: PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
710: {
712: PetscObjectSetOptionsPrefix((PetscObject)A, prefix);
713: return 0;
714: }
716: /*@C
717: MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
718: for matrices created with `MatGetFactor()`
720: Logically Collective on A
722: Input Parameters:
723: + A - the matrix
724: - prefix - the prefix to prepend to all option names for the factored matrix
726: Notes:
727: A hyphen (-) must NOT be given at the beginning of the prefix name.
728: The first character of all runtime options is AUTOMATICALLY the hyphen.
730: Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
731: it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()`
733: Level: developer
735: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
736: @*/
737: PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
738: {
740: if (prefix) {
743: if (prefix != A->factorprefix) {
744: PetscFree(A->factorprefix);
745: PetscStrallocpy(prefix, &A->factorprefix);
746: }
747: } else PetscFree(A->factorprefix);
748: return 0;
749: }
751: /*@C
752: MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
753: for matrices created with `MatGetFactor()`
755: Logically Collective on A
757: Input Parameters:
758: + A - the matrix
759: - prefix - the prefix to prepend to all option names for the factored matrix
761: Notes:
762: A hyphen (-) must NOT be given at the beginning of the prefix name.
763: The first character of all runtime options is AUTOMATICALLY the hyphen.
765: Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
766: it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()`
768: Level: developer
770: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
771: `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
772: `MatSetOptionsPrefix()`
773: @*/
774: PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
775: {
776: char *buf = A->factorprefix;
777: size_t len1, len2;
780: if (!prefix) return 0;
781: if (!buf) {
782: MatSetOptionsPrefixFactor(A, prefix);
783: return 0;
784: }
787: PetscStrlen(prefix, &len1);
788: PetscStrlen(buf, &len2);
789: PetscMalloc1(1 + len1 + len2, &A->factorprefix);
790: PetscStrcpy(A->factorprefix, buf);
791: PetscStrcat(A->factorprefix, prefix);
792: PetscFree(buf);
793: return 0;
794: }
796: /*@C
797: MatAppendOptionsPrefix - Appends to the prefix used for searching for all
798: matrix options in the database.
800: Logically Collective on A
802: Input Parameters:
803: + A - the matrix
804: - prefix - the prefix to prepend to all option names
806: Note:
807: A hyphen (-) must NOT be given at the beginning of the prefix name.
808: The first character of all runtime options is AUTOMATICALLY the hyphen.
810: Level: advanced
812: .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
813: @*/
814: PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
815: {
817: PetscObjectAppendOptionsPrefix((PetscObject)A, prefix);
818: return 0;
819: }
821: /*@C
822: MatGetOptionsPrefix - Gets the prefix used for searching for all
823: matrix options in the database.
825: Not Collective
827: Input Parameter:
828: . A - the matrix
830: Output Parameter:
831: . prefix - pointer to the prefix string used
833: Fortran Note:
834: On the fortran side, the user should pass in a string 'prefix' of
835: sufficient length to hold the prefix.
837: Level: advanced
839: .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
840: @*/
841: PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
842: {
845: PetscObjectGetOptionsPrefix((PetscObject)A, prefix);
846: return 0;
847: }
849: /*@
850: MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
852: Collective on A
854: Input Parameters:
855: . A - the matrix
857: Notes:
858: The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
860: Users can reset the preallocation to access the original memory.
862: Currently only supported for `MATMPIAIJ` and `MATSEQAIJ` matrices.
864: Level: beginner
866: .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
867: @*/
868: PetscErrorCode MatResetPreallocation(Mat A)
869: {
872: PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
873: return 0;
874: }
876: /*@
877: MatSetUp - Sets up the internal matrix data structures for later use.
879: Collective on A
881: Input Parameters:
882: . A - the matrix
884: Notes:
885: If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
887: If a suitable preallocation routine is used, this function does not need to be called.
889: See the Performance chapter of the PETSc users manual for how to preallocate matrices
891: This routine is called internally by other matrix functions when needed so rarely needs to be called by users
893: Level: intermediate
895: .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
896: @*/
897: PetscErrorCode MatSetUp(Mat A)
898: {
900: if (!((PetscObject)A)->type_name) {
901: PetscMPIInt size;
903: MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);
904: MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ);
905: }
906: if (!A->preallocated && A->ops->setup) {
907: PetscInfo(A, "Warning not preallocating matrix storage\n");
908: PetscUseTypeMethod(A, setup);
909: }
910: PetscLayoutSetUp(A->rmap);
911: PetscLayoutSetUp(A->cmap);
912: A->preallocated = PETSC_TRUE;
913: return 0;
914: }
916: #if defined(PETSC_HAVE_SAWS)
917: #include <petscviewersaws.h>
918: #endif
920: /*@C
921: MatViewFromOptions - View properties of the matrix from the options database
923: Collective on A
925: Input Parameters:
926: + A - the matrix
927: . obj - optional additional object that provides the options prefix to use
928: - name - command line option
930: Options Database 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 on mat
961: Input Parameters:
962: + mat - the matrix
963: - viewer - visualization context
965: Notes:
966: The available visualization contexts include
967: + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
968: . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
969: . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
970: - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
972: The user can open alternative visualization contexts with
973: + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
974: . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
975: specified file; corresponding input uses MatLoad()
976: . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
977: an X window display
978: - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
979: Currently only the sequential dense and AIJ
980: matrix types support the Socket viewer.
982: The user can call `PetscViewerPushFormat()` to specify the output
983: format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
984: `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include
985: + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
986: . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
987: . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
988: . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
989: format common among all matrix types
990: . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
991: format (which is in many cases the same as the default)
992: . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
993: size and structure (not the matrix entries)
994: - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
995: the matrix structure
997: Options Database Keys:
998: + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
999: . -mat_view ::ascii_info_detail - Prints more detailed info
1000: . -mat_view - Prints matrix in ASCII format
1001: . -mat_view ::ascii_matlab - Prints matrix in Matlab format
1002: . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1003: . -display <name> - Sets display name (default is host)
1004: . -draw_pause <sec> - Sets number of seconds to pause after display
1005: . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1006: . -viewer_socket_machine <machine> -
1007: . -viewer_socket_port <port> -
1008: . -mat_view binary - save matrix to file in binary format
1009: - -viewer_binary_filename <name> -
1011: Level: beginner
1013: Notes:
1014: The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1015: the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1017: In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1019: See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1020: viewer is used.
1022: See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1023: viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1025: One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1026: and then use the following mouse functions.
1027: .vb
1028: left mouse: zoom in
1029: middle mouse: zoom out
1030: right mouse: continue with the simulation
1031: .ve
1033: .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`,
1034: `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1035: @*/
1036: PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1037: {
1038: PetscInt rows, cols, rbs, cbs;
1039: PetscBool isascii, isstring, issaws;
1040: PetscViewerFormat format;
1041: PetscMPIInt size;
1045: if (!viewer) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer);
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 on mat
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: Notes:
1464: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1465: `MatSetUp()` before using this routine
1467: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1469: Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1470: options cannot be mixed without intervening calls to the assembly
1471: routines.
1473: MatSetValues() uses 0-based row and column numbers in Fortran
1474: as well as in C.
1476: Negative indices may be passed in ism and isn, these rows and columns are
1477: simply ignored. This allows easily inserting element stiffness matrices
1478: with homogeneous Dirchlet boundary conditions that you don't want represented
1479: in the matrix.
1481: Efficiency Alert:
1482: The routine `MatSetValuesBlocked()` may offer much better efficiency
1483: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1485: Level: beginner
1487: Developer Notes:
1488: This is labeled with C so does not automatically generate Fortran stubs and interfaces
1489: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1491: This is currently not optimized for any particular `ISType`
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: Notes:
1612: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1614: Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1615: options cannot be mixed without intervening calls to the assembly
1616: routines.
1618: The grid coordinates are across the entire grid, not just the local portion
1620: `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1621: as well as in C.
1623: For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1625: In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1626: or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1628: The columns and rows in the stencil passed in MUST be contained within the
1629: ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1630: if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1631: local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1632: first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1634: In Fortran idxm and idxn should be declared as
1635: $ MatStencil idxm(4,m),idxn(4,n)
1636: and the values inserted using
1637: $ idxm(MatStencil_i,1) = i
1638: $ idxm(MatStencil_j,1) = j
1639: $ idxm(MatStencil_k,1) = k
1640: $ idxm(MatStencil_c,1) = c
1641: etc
1643: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1644: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1645: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1646: `DM_BOUNDARY_PERIODIC` boundary type.
1648: 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
1649: a single value per point) you can skip filling those indices.
1651: Inspired by the structured grid interface to the HYPRE package
1652: (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1654: Efficiency Alert:
1655: The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1656: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1658: Level: beginner
1660: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1661: `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1662: @*/
1663: PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1664: {
1665: PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1666: PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1667: PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1669: if (!m || !n) return 0; /* no values to insert */
1675: if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1676: jdxm = buf;
1677: jdxn = buf + m;
1678: } else {
1679: PetscMalloc2(m, &bufm, n, &bufn);
1680: jdxm = bufm;
1681: jdxn = bufn;
1682: }
1683: for (i = 0; i < m; i++) {
1684: for (j = 0; j < 3 - sdim; j++) dxm++;
1685: tmp = *dxm++ - starts[0];
1686: for (j = 0; j < dim - 1; j++) {
1687: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1688: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1689: }
1690: if (mat->stencil.noc) dxm++;
1691: jdxm[i] = tmp;
1692: }
1693: for (i = 0; i < n; i++) {
1694: for (j = 0; j < 3 - sdim; j++) dxn++;
1695: tmp = *dxn++ - starts[0];
1696: for (j = 0; j < dim - 1; j++) {
1697: if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1698: else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1699: }
1700: if (mat->stencil.noc) dxn++;
1701: jdxn[i] = tmp;
1702: }
1703: MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv);
1704: PetscFree2(bufm, bufn);
1705: return 0;
1706: }
1708: /*@
1709: MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1710: Using structured grid indexing
1712: Not Collective
1714: Input Parameters:
1715: + mat - the matrix
1716: . m - number of rows being entered
1717: . idxm - grid coordinates for matrix rows being entered
1718: . n - number of columns being entered
1719: . idxn - grid coordinates for matrix columns being entered
1720: . v - a logically two-dimensional array of values
1721: - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1723: Notes:
1724: By default the values, v, are row-oriented and unsorted.
1725: See `MatSetOption()` for other options.
1727: Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1728: options cannot be mixed without intervening calls to the assembly
1729: routines.
1731: The grid coordinates are across the entire grid, not just the local portion
1733: `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1734: as well as in C.
1736: For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1738: In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1739: or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1741: The columns and rows in the stencil passed in MUST be contained within the
1742: ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1743: if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1744: local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1745: first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1747: In Fortran idxm and idxn should be declared as
1748: $ MatStencil idxm(4,m),idxn(4,n)
1749: and the values inserted using
1750: $ idxm(MatStencil_i,1) = i
1751: $ idxm(MatStencil_j,1) = j
1752: $ idxm(MatStencil_k,1) = k
1753: etc
1755: Negative indices may be passed in idxm and idxn, these rows and columns are
1756: simply ignored. This allows easily inserting element stiffness matrices
1757: with homogeneous Dirchlet boundary conditions that you don't want represented
1758: in the matrix.
1760: Inspired by the structured grid interface to the HYPRE package
1761: (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1763: Level: beginner
1765: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1766: `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1767: `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1768: @*/
1769: PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1770: {
1771: PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1772: PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1773: PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1775: if (!m || !n) return 0; /* no values to insert */
1782: if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1783: jdxm = buf;
1784: jdxn = buf + m;
1785: } else {
1786: PetscMalloc2(m, &bufm, n, &bufn);
1787: jdxm = bufm;
1788: jdxn = bufn;
1789: }
1790: for (i = 0; i < m; i++) {
1791: for (j = 0; j < 3 - sdim; j++) dxm++;
1792: tmp = *dxm++ - starts[0];
1793: for (j = 0; j < sdim - 1; j++) {
1794: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1795: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1796: }
1797: dxm++;
1798: jdxm[i] = tmp;
1799: }
1800: for (i = 0; i < n; i++) {
1801: for (j = 0; j < 3 - sdim; j++) dxn++;
1802: tmp = *dxn++ - starts[0];
1803: for (j = 0; j < sdim - 1; j++) {
1804: if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1805: else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1806: }
1807: dxn++;
1808: jdxn[i] = tmp;
1809: }
1810: MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv);
1811: PetscFree2(bufm, bufn);
1812: return 0;
1813: }
1815: /*@
1816: MatSetStencil - Sets the grid information for setting values into a matrix via
1817: `MatSetValuesStencil()`
1819: Not Collective
1821: Input Parameters:
1822: + mat - the matrix
1823: . dim - dimension of the grid 1, 2, or 3
1824: . dims - number of grid points in x, y, and z direction, including ghost points on your processor
1825: . starts - starting point of ghost nodes on your processor in x, y, and z direction
1826: - dof - number of degrees of freedom per node
1828: Notes:
1829: Inspired by the structured grid interface to the HYPRE package
1830: (www.llnl.gov/CASC/hyper)
1832: For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1833: user.
1835: Level: beginner
1837: .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1838: `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1839: @*/
1840: PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1841: {
1846: mat->stencil.dim = dim + (dof > 1);
1847: for (PetscInt i = 0; i < dim; i++) {
1848: mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */
1849: mat->stencil.starts[i] = starts[dim - i - 1];
1850: }
1851: mat->stencil.dims[dim] = dof;
1852: mat->stencil.starts[dim] = 0;
1853: mat->stencil.noc = (PetscBool)(dof == 1);
1854: return 0;
1855: }
1857: /*@C
1858: MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1860: Not Collective
1862: Input Parameters:
1863: + mat - the matrix
1864: . v - a logically two-dimensional array of values
1865: . m, idxm - the number of block rows and their global block indices
1866: . n, idxn - the number of block columns and their global block indices
1867: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1869: Notes:
1870: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1871: MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1873: The m and n count the NUMBER of blocks in the row direction and column direction,
1874: NOT the total number of rows/columns; for example, if the block size is 2 and
1875: you are passing in values for rows 2,3,4,5 then m would be 2 (not 4).
1876: The values in idxm would be 1 2; that is the first index for each block divided by
1877: the block size.
1879: Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1880: preallocating it).
1882: By default the values, v, are row-oriented, so the layout of
1883: v is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1885: Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1886: options cannot be mixed without intervening calls to the assembly
1887: routines.
1889: `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1890: as well as in C.
1892: Negative indices may be passed in idxm and idxn, these rows and columns are
1893: simply ignored. This allows easily inserting element stiffness matrices
1894: with homogeneous Dirchlet boundary conditions that you don't want represented
1895: in the matrix.
1897: Each time an entry is set within a sparse matrix via `MatSetValues()`,
1898: internal searching must be done to determine where to place the
1899: data in the matrix storage space. By instead inserting blocks of
1900: entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1901: reduced.
1903: Example:
1904: $ Suppose m=n=2 and block size(bs) = 2 The array is
1905: $
1906: $ 1 2 | 3 4
1907: $ 5 6 | 7 8
1908: $ - - - | - - -
1909: $ 9 10 | 11 12
1910: $ 13 14 | 15 16
1911: $
1912: $ v[] should be passed in like
1913: $ v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1914: $
1915: $ If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1916: $ v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1918: Level: intermediate
1920: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1921: @*/
1922: PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1923: {
1927: if (!m || !n) return 0; /* no values to insert */
1930: MatCheckPreallocated(mat, 1);
1931: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1933: if (PetscDefined(USE_DEBUG)) {
1936: }
1937: if (PetscDefined(USE_DEBUG)) {
1938: PetscInt rbs, cbs, M, N, i;
1939: MatGetBlockSizes(mat, &rbs, &cbs);
1940: MatGetSize(mat, &M, &N);
1943: }
1944: if (mat->assembled) {
1945: mat->was_assembled = PETSC_TRUE;
1946: mat->assembled = PETSC_FALSE;
1947: }
1948: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1949: if (mat->ops->setvaluesblocked) {
1950: PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1951: } else {
1952: PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1953: PetscInt i, j, bs, cbs;
1955: MatGetBlockSizes(mat, &bs, &cbs);
1956: if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1957: iidxm = buf;
1958: iidxn = buf + m * bs;
1959: } else {
1960: PetscMalloc2(m * bs, &bufr, n * cbs, &bufc);
1961: iidxm = bufr;
1962: iidxn = bufc;
1963: }
1964: for (i = 0; i < m; i++) {
1965: for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
1966: }
1967: if (m != n || bs != cbs || idxm != idxn) {
1968: for (i = 0; i < n; i++) {
1969: for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
1970: }
1971: } else iidxn = iidxm;
1972: MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv);
1973: PetscFree2(bufr, bufc);
1974: }
1975: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1976: return 0;
1977: }
1979: /*@C
1980: MatGetValues - Gets a block of local values from a matrix.
1982: Not Collective; can only return values that are owned by the give process
1984: Input Parameters:
1985: + mat - the matrix
1986: . v - a logically two-dimensional array for storing the values
1987: . m, idxm - the number of rows and their global indices
1988: - n, idxn - the number of columns and their global indices
1990: Notes:
1991: The user must allocate space (m*n `PetscScalar`s) for the values, v.
1992: The values, v, are then returned in a row-oriented format,
1993: analogous to that used by default in `MatSetValues()`.
1995: `MatGetValues()` uses 0-based row and column numbers in
1996: Fortran as well as in C.
1998: `MatGetValues()` requires that the matrix has been assembled
1999: with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to
2000: `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2001: without intermediate matrix assembly.
2003: Negative row or column indices will be ignored and those locations in v[] will be
2004: left unchanged.
2006: For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2007: That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2008: from `MatGetOwnershipRange`(mat,&rstart,&rend).
2010: Level: advanced
2012: .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2013: @*/
2014: PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2015: {
2018: if (!m || !n) return 0;
2024: MatCheckPreallocated(mat, 1);
2026: PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2027: PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2028: PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2029: return 0;
2030: }
2032: /*@C
2033: MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2034: defined previously by `MatSetLocalToGlobalMapping()`
2036: Not Collective
2038: Input Parameters:
2039: + mat - the matrix
2040: . nrow, irow - number of rows and their local indices
2041: - ncol, icol - number of columns and their local indices
2043: Output Parameter:
2044: . y - a logically two-dimensional array of values
2046: Notes:
2047: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2049: 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,
2050: are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2051: determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2052: with `MatSetLocalToGlobalMapping()`.
2054: Developer Note:
2055: This is labelled with C so does not automatically generate Fortran stubs and interfaces
2056: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2058: Level: advanced
2060: .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2061: `MatSetValuesLocal()`, `MatGetValues()`
2062: @*/
2063: PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2064: {
2068: MatCheckPreallocated(mat, 1);
2069: if (!nrow || !ncol) return 0; /* no values to retrieve */
2072: if (PetscDefined(USE_DEBUG)) {
2075: }
2077: PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2078: if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2079: else {
2080: PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2081: if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2082: irowm = buf;
2083: icolm = buf + nrow;
2084: } else {
2085: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2086: irowm = bufr;
2087: icolm = bufc;
2088: }
2091: ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm);
2092: ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm);
2093: MatGetValues(mat, nrow, irowm, ncol, icolm, y);
2094: PetscFree2(bufr, bufc);
2095: }
2096: PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2097: return 0;
2098: }
2100: /*@
2101: MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2102: the same size. Currently, this can only be called once and creates the given matrix.
2104: Not Collective
2106: Input Parameters:
2107: + mat - the matrix
2108: . nb - the number of blocks
2109: . bs - the number of rows (and columns) in each block
2110: . rows - a concatenation of the rows for each block
2111: - v - a concatenation of logically two-dimensional arrays of values
2113: Note:
2114: `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2116: In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2118: Level: advanced
2120: .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2121: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2122: @*/
2123: PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2124: {
2129: PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2131: PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0);
2132: if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2133: else {
2134: for (PetscInt b = 0; b < nb; ++b) MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES);
2135: }
2136: PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0);
2137: return 0;
2138: }
2140: /*@
2141: MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2142: the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2143: using a local (per-processor) numbering.
2145: Not Collective
2147: Input Parameters:
2148: + x - the matrix
2149: . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2150: - cmapping - column mapping
2152: Level: intermediate
2154: Note:
2155: If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2157: .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2158: @*/
2159: PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2160: {
2165: if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2166: else {
2167: PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping);
2168: PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping);
2169: }
2170: return 0;
2171: }
2173: /*@
2174: MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2176: Not Collective
2178: Input Parameter:
2179: . A - the matrix
2181: Output Parameters:
2182: + rmapping - row mapping
2183: - cmapping - column mapping
2185: Level: advanced
2187: .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2188: @*/
2189: PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2190: {
2193: if (rmapping) {
2195: *rmapping = A->rmap->mapping;
2196: }
2197: if (cmapping) {
2199: *cmapping = A->cmap->mapping;
2200: }
2201: return 0;
2202: }
2204: /*@
2205: MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2207: Logically Collective on A
2209: Input Parameters:
2210: + A - the matrix
2211: . rmap - row layout
2212: - cmap - column layout
2214: Level: advanced
2216: Note:
2217: The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2219: .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2220: @*/
2221: PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2222: {
2224: PetscLayoutReference(rmap, &A->rmap);
2225: PetscLayoutReference(cmap, &A->cmap);
2226: return 0;
2227: }
2229: /*@
2230: MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2232: Not Collective
2234: Input Parameter:
2235: . A - the matrix
2237: Output Parameters:
2238: + rmap - row layout
2239: - cmap - column layout
2241: Level: advanced
2243: .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2244: @*/
2245: PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2246: {
2249: if (rmap) {
2251: *rmap = A->rmap;
2252: }
2253: if (cmap) {
2255: *cmap = A->cmap;
2256: }
2257: return 0;
2258: }
2260: /*@C
2261: MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2262: using a local numbering of the nodes.
2264: Not Collective
2266: Input Parameters:
2267: + mat - the matrix
2268: . nrow, irow - number of rows and their local indices
2269: . ncol, icol - number of columns and their local indices
2270: . y - a logically two-dimensional array of values
2271: - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2273: Notes:
2274: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2275: `MatSetUp()` before using this routine
2277: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2279: Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2280: options cannot be mixed without intervening calls to the assembly
2281: routines.
2283: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2284: MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2286: Level: intermediate
2288: Developer Note:
2289: This is labeled with C so does not automatically generate Fortran stubs and interfaces
2290: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2292: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2293: `MatGetValuesLocal()`
2294: @*/
2295: PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2296: {
2300: MatCheckPreallocated(mat, 1);
2301: if (!nrow || !ncol) return 0; /* no values to insert */
2304: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2306: if (PetscDefined(USE_DEBUG)) {
2309: }
2311: if (mat->assembled) {
2312: mat->was_assembled = PETSC_TRUE;
2313: mat->assembled = PETSC_FALSE;
2314: }
2315: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2316: if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2317: else {
2318: PetscInt buf[8192], *bufr = NULL, *bufc = NULL;
2319: const PetscInt *irowm, *icolm;
2321: if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2322: bufr = buf;
2323: bufc = buf + nrow;
2324: irowm = bufr;
2325: icolm = bufc;
2326: } else {
2327: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2328: irowm = bufr;
2329: icolm = bufc;
2330: }
2331: if (mat->rmap->mapping) ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr);
2332: else irowm = irow;
2333: if (mat->cmap->mapping) {
2334: if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2335: ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc);
2336: } else icolm = irowm;
2337: } else icolm = icol;
2338: MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv);
2339: if (bufr != buf) PetscFree2(bufr, bufc);
2340: }
2341: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2342: return 0;
2343: }
2345: /*@C
2346: MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2347: using a local ordering of the nodes a block at a time.
2349: Not Collective
2351: Input Parameters:
2352: + x - the matrix
2353: . nrow, irow - number of rows and their local indices
2354: . ncol, icol - number of columns and their local indices
2355: . y - a logically two-dimensional array of values
2356: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2358: Notes:
2359: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2360: `MatSetUp()` before using this routine
2362: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2363: before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2365: Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2366: options cannot be mixed without intervening calls to the assembly
2367: routines.
2369: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2370: MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2372: Level: intermediate
2374: Developer Note:
2375: This is labeled with C so does not automatically generate Fortran stubs and interfaces
2376: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2378: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2379: `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2380: @*/
2381: PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2382: {
2386: MatCheckPreallocated(mat, 1);
2387: if (!nrow || !ncol) return 0; /* no values to insert */
2390: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2392: if (PetscDefined(USE_DEBUG)) {
2395: }
2397: if (mat->assembled) {
2398: mat->was_assembled = PETSC_TRUE;
2399: mat->assembled = PETSC_FALSE;
2400: }
2401: if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2402: PetscInt irbs, rbs;
2403: MatGetBlockSizes(mat, &rbs, NULL);
2404: ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs);
2406: }
2407: if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2408: PetscInt icbs, cbs;
2409: MatGetBlockSizes(mat, NULL, &cbs);
2410: ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs);
2412: }
2413: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2414: if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2415: else {
2416: PetscInt buf[8192], *bufr = NULL, *bufc = NULL;
2417: const PetscInt *irowm, *icolm;
2419: if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2420: bufr = buf;
2421: bufc = buf + nrow;
2422: irowm = bufr;
2423: icolm = bufc;
2424: } else {
2425: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2426: irowm = bufr;
2427: icolm = bufc;
2428: }
2429: if (mat->rmap->mapping) ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr);
2430: else irowm = irow;
2431: if (mat->cmap->mapping) {
2432: if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2433: ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc);
2434: } else icolm = irowm;
2435: } else icolm = icol;
2436: MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv);
2437: if (bufr != buf) PetscFree2(bufr, bufc);
2438: }
2439: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2440: return 0;
2441: }
2443: /*@
2444: MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2446: Collective on mat
2448: Input Parameters:
2449: + mat - the matrix
2450: - x - the vector to be multiplied
2452: Output Parameters:
2453: . y - the result
2455: Note:
2456: The vectors x and y cannot be the same. I.e., one cannot
2457: call `MatMultDiagonalBlock`(A,y,y).
2459: Level: developer
2461: .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2462: @*/
2463: PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2464: {
2473: MatCheckPreallocated(mat, 1);
2475: PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2476: PetscObjectStateIncrease((PetscObject)y);
2477: return 0;
2478: }
2480: /* --------------------------------------------------------*/
2481: /*@
2482: MatMult - Computes the matrix-vector product, y = Ax.
2484: Neighbor-wise Collective on mat
2486: Input Parameters:
2487: + mat - the matrix
2488: - x - the vector to be multiplied
2490: Output Parameters:
2491: . y - the result
2493: Note:
2494: The vectors x and y cannot be the same. I.e., one cannot
2495: call `MatMult`(A,y,y).
2497: Level: beginner
2499: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2500: @*/
2501: PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2502: {
2514: VecSetErrorIfLocked(y, 3);
2515: if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2516: MatCheckPreallocated(mat, 1);
2518: VecLockReadPush(x);
2519: PetscLogEventBegin(MAT_Mult, mat, x, y, 0);
2520: PetscUseTypeMethod(mat, mult, x, y);
2521: PetscLogEventEnd(MAT_Mult, mat, x, y, 0);
2522: if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2523: VecLockReadPop(x);
2524: return 0;
2525: }
2527: /*@
2528: MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2530: Neighbor-wise Collective on mat
2532: Input Parameters:
2533: + mat - the matrix
2534: - x - the vector to be multiplied
2536: Output Parameters:
2537: . y - the result
2539: Notes:
2540: The vectors x and y cannot be the same. I.e., one cannot
2541: call `MatMultTranspose`(A,y,y).
2543: For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2544: use `MatMultHermitianTranspose()`
2546: Level: beginner
2548: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2549: @*/
2550: PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2551: {
2552: PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2566: if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2567: MatCheckPreallocated(mat, 1);
2569: if (!mat->ops->multtranspose) {
2570: if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2572: } else op = mat->ops->multtranspose;
2573: PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0);
2574: VecLockReadPush(x);
2575: (*op)(mat, x, y);
2576: VecLockReadPop(x);
2577: PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0);
2578: PetscObjectStateIncrease((PetscObject)y);
2579: if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2580: return 0;
2581: }
2583: /*@
2584: MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2586: Neighbor-wise Collective on mat
2588: Input Parameters:
2589: + mat - the matrix
2590: - x - the vector to be multilplied
2592: Output Parameters:
2593: . y - the result
2595: Notes:
2596: The vectors x and y cannot be the same. I.e., one cannot
2597: call `MatMultHermitianTranspose`(A,y,y).
2599: Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2601: For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2603: Level: beginner
2605: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2606: @*/
2607: PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2608: {
2621: MatCheckPreallocated(mat, 1);
2623: PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0);
2624: #if defined(PETSC_USE_COMPLEX)
2625: if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2626: VecLockReadPush(x);
2627: if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2628: else PetscUseTypeMethod(mat, mult, x, y);
2629: VecLockReadPop(x);
2630: } else {
2631: Vec w;
2632: VecDuplicate(x, &w);
2633: VecCopy(x, w);
2634: VecConjugate(w);
2635: MatMultTranspose(mat, w, y);
2636: VecDestroy(&w);
2637: VecConjugate(y);
2638: }
2639: PetscObjectStateIncrease((PetscObject)y);
2640: #else
2641: MatMultTranspose(mat, x, y);
2642: #endif
2643: PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0);
2644: return 0;
2645: }
2647: /*@
2648: MatMultAdd - Computes v3 = v2 + A * v1.
2650: Neighbor-wise Collective on mat
2652: Input Parameters:
2653: + mat - the matrix
2654: - v1, v2 - the vectors
2656: Output Parameters:
2657: . v3 - the result
2659: Note:
2660: The vectors v1 and v3 cannot be the same. I.e., one cannot
2661: call `MatMultAdd`(A,v1,v2,v1).
2663: Level: beginner
2665: .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2666: @*/
2667: PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2668: {
2683: MatCheckPreallocated(mat, 1);
2685: PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3);
2686: VecLockReadPush(v1);
2687: PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2688: VecLockReadPop(v1);
2689: PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3);
2690: PetscObjectStateIncrease((PetscObject)v3);
2691: return 0;
2692: }
2694: /*@
2695: MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2697: Neighbor-wise Collective on mat
2699: Input Parameters:
2700: + mat - the matrix
2701: - v1, v2 - the vectors
2703: Output Parameters:
2704: . v3 - the result
2706: Note:
2707: The vectors v1 and v3 cannot be the same. I.e., one cannot
2708: call `MatMultTransposeAdd`(A,v1,v2,v1).
2710: Level: beginner
2712: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2713: @*/
2714: PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2715: {
2716: PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2731: MatCheckPreallocated(mat, 1);
2733: PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3);
2734: VecLockReadPush(v1);
2735: (*op)(mat, v1, v2, v3);
2736: VecLockReadPop(v1);
2737: PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3);
2738: PetscObjectStateIncrease((PetscObject)v3);
2739: return 0;
2740: }
2742: /*@
2743: MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2745: Neighbor-wise Collective on mat
2747: Input Parameters:
2748: + mat - the matrix
2749: - v1, v2 - the vectors
2751: Output Parameters:
2752: . v3 - the result
2754: Note:
2755: The vectors v1 and v3 cannot be the same. I.e., one cannot
2756: call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2758: Level: beginner
2760: .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2761: @*/
2762: PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2763: {
2776: MatCheckPreallocated(mat, 1);
2778: PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2779: VecLockReadPush(v1);
2780: if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2781: else {
2782: Vec w, z;
2783: VecDuplicate(v1, &w);
2784: VecCopy(v1, w);
2785: VecConjugate(w);
2786: VecDuplicate(v3, &z);
2787: MatMultTranspose(mat, w, z);
2788: VecDestroy(&w);
2789: VecConjugate(z);
2790: if (v2 != v3) {
2791: VecWAXPY(v3, 1.0, v2, z);
2792: } else {
2793: VecAXPY(v3, 1.0, z);
2794: }
2795: VecDestroy(&z);
2796: }
2797: VecLockReadPop(v1);
2798: PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2799: PetscObjectStateIncrease((PetscObject)v3);
2800: return 0;
2801: }
2803: /*@C
2804: MatGetFactorType - gets the type of factorization it is
2806: Not Collective
2808: Input Parameters:
2809: . mat - the matrix
2811: Output Parameters:
2812: . 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`
2814: Level: intermediate
2816: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2817: `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2818: @*/
2819: PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2820: {
2824: *t = mat->factortype;
2825: return 0;
2826: }
2828: /*@C
2829: MatSetFactorType - sets the type of factorization it is
2831: Logically Collective on mat
2833: Input Parameters:
2834: + mat - the matrix
2835: - 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`
2837: Level: intermediate
2839: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2840: `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2841: @*/
2842: PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2843: {
2846: mat->factortype = t;
2847: return 0;
2848: }
2850: /* ------------------------------------------------------------*/
2851: /*@C
2852: MatGetInfo - Returns information about matrix storage (number of
2853: nonzeros, memory, etc.).
2855: Collective on mat if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2857: Input Parameter:
2858: . mat - the matrix
2860: Output Parameters:
2861: + flag - flag indicating the type of parameters to be returned
2862: (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors,
2863: MAT_GLOBAL_SUM - sum over all processors)
2864: - info - matrix information context
2866: Notes:
2867: The `MatInfo` context contains a variety of matrix data, including
2868: number of nonzeros allocated and used, number of mallocs during
2869: matrix assembly, etc. Additional information for factored matrices
2870: is provided (such as the fill ratio, number of mallocs during
2871: factorization, etc.). Much of this info is printed to `PETSC_STDOUT`
2872: when using the runtime options
2873: $ -info -mat_view ::ascii_info
2875: Example for C/C++ Users:
2876: See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2877: data within the MatInfo context. For example,
2878: .vb
2879: MatInfo info;
2880: Mat A;
2881: double mal, nz_a, nz_u;
2883: MatGetInfo(A,MAT_LOCAL,&info);
2884: mal = info.mallocs;
2885: nz_a = info.nz_allocated;
2886: .ve
2888: Example for Fortran Users:
2889: Fortran users should declare info as a double precision
2890: array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2891: of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2892: a complete list of parameter names.
2893: .vb
2894: double precision info(MAT_INFO_SIZE)
2895: double precision mal, nz_a
2896: Mat A
2897: integer ierr
2899: call MatGetInfo(A,MAT_LOCAL,info,ierr)
2900: mal = info(MAT_INFO_MALLOCS)
2901: nz_a = info(MAT_INFO_NZ_ALLOCATED)
2902: .ve
2904: Level: intermediate
2906: Developer Note: fortran interface is not autogenerated as the f90
2907: interface definition cannot be generated correctly [due to MatInfo]
2909: .seealso: `MatInfo`, `MatStashGetInfo()`
2910: @*/
2911: PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2912: {
2916: MatCheckPreallocated(mat, 1);
2917: PetscUseTypeMethod(mat, getinfo, flag, info);
2918: return 0;
2919: }
2921: /*
2922: This is used by external packages where it is not easy to get the info from the actual
2923: matrix factorization.
2924: */
2925: PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2926: {
2927: PetscMemzero(info, sizeof(MatInfo));
2928: return 0;
2929: }
2931: /* ----------------------------------------------------------*/
2933: /*@C
2934: MatLUFactor - Performs in-place LU factorization of matrix.
2936: Collective on mat
2938: Input Parameters:
2939: + mat - the matrix
2940: . row - row permutation
2941: . col - column permutation
2942: - info - options for factorization, includes
2943: $ fill - expected fill as ratio of original fill.
2944: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2945: $ Run with the option -info to determine an optimal value to use
2947: Notes:
2948: Most users should employ the `KSP` interface for linear solvers
2949: instead of working directly with matrix algebra routines such as this.
2950: See, e.g., `KSPCreate()`.
2952: This changes the state of the matrix to a factored matrix; it cannot be used
2953: for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
2955: This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
2956: when not using `KSP`.
2958: Level: developer
2960: Developer Note:
2961: The Fortran interface is not autogenerated as the f90
2962: interface definition cannot be generated correctly [due to `MatFactorInfo`]
2964: .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2965: `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2966: @*/
2967: PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
2968: {
2969: MatFactorInfo tinfo;
2978: MatCheckPreallocated(mat, 1);
2979: if (!info) {
2980: MatFactorInfoInitialize(&tinfo);
2981: info = &tinfo;
2982: }
2984: PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0);
2985: PetscUseTypeMethod(mat, lufactor, row, col, info);
2986: PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0);
2987: PetscObjectStateIncrease((PetscObject)mat);
2988: return 0;
2989: }
2991: /*@C
2992: MatILUFactor - Performs in-place ILU factorization of matrix.
2994: Collective on mat
2996: Input Parameters:
2997: + mat - the matrix
2998: . row - row permutation
2999: . col - column permutation
3000: - info - structure containing
3001: $ levels - number of levels of fill.
3002: $ expected fill - as ratio of original fill.
3003: $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3004: missing diagonal entries)
3006: Notes:
3007: Most users should employ the `KSP` interface for linear solvers
3008: instead of working directly with matrix algebra routines such as this.
3009: See, e.g., `KSPCreate()`.
3011: Probably really in-place only when level of fill is zero, otherwise allocates
3012: new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3013: when not using `KSP`.
3015: Level: developer
3017: Developer Note:
3018: The Fortran interface is not autogenerated as the f90
3019: interface definition cannot be generated correctly [due to MatFactorInfo]
3021: .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3022: @*/
3023: PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3024: {
3033: MatCheckPreallocated(mat, 1);
3035: PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0);
3036: PetscUseTypeMethod(mat, ilufactor, row, col, info);
3037: PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0);
3038: PetscObjectStateIncrease((PetscObject)mat);
3039: return 0;
3040: }
3042: /*@C
3043: MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3044: Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3046: Collective on fact
3048: Input Parameters:
3049: + fact - the factor matrix obtained with `MatGetFactor()`
3050: . mat - the matrix
3051: . row, col - row and column permutations
3052: - info - options for factorization, includes
3053: .vb
3054: fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3055: dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3056: .ve
3058: Notes:
3059: See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3061: Most users should employ the simplified `KSP` interface for linear solvers
3062: instead of working directly with matrix algebra routines such as this.
3063: See, e.g., `KSPCreate()`.
3065: Level: developer
3067: Developer Note:
3068: The Fortran interface is not autogenerated as the f90
3069: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3071: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3072: @*/
3073: PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3074: {
3075: MatFactorInfo tinfo;
3085: if (!(fact)->ops->lufactorsymbolic) {
3086: MatSolverType stype;
3087: MatFactorGetSolverType(fact, &stype);
3088: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3089: }
3090: MatCheckPreallocated(mat, 2);
3091: if (!info) {
3092: MatFactorInfoInitialize(&tinfo);
3093: info = &tinfo;
3094: }
3096: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0);
3097: (fact->ops->lufactorsymbolic)(fact, mat, row, col, info);
3098: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0);
3099: PetscObjectStateIncrease((PetscObject)fact);
3100: return 0;
3101: }
3103: /*@C
3104: MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3105: Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3107: Collective on fact
3109: Input Parameters:
3110: + fact - the factor matrix obtained with `MatGetFactor()`
3111: . mat - the matrix
3112: - info - options for factorization
3114: Notes:
3115: See `MatLUFactor()` for in-place factorization. See
3116: `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3118: Most users should employ the `KSP` interface for linear solvers
3119: instead of working directly with matrix algebra routines such as this.
3120: See, e.g., `KSPCreate()`.
3122: Level: developer
3124: Developer Note:
3125: The Fortran interface is not autogenerated as the f90
3126: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3128: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3129: @*/
3130: PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3131: {
3132: MatFactorInfo tinfo;
3140: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3143: MatCheckPreallocated(mat, 2);
3144: if (!info) {
3145: MatFactorInfoInitialize(&tinfo);
3146: info = &tinfo;
3147: }
3149: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0);
3150: else PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0);
3151: (fact->ops->lufactornumeric)(fact, mat, info);
3152: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0);
3153: else PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0);
3154: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3155: PetscObjectStateIncrease((PetscObject)fact);
3156: return 0;
3157: }
3159: /*@C
3160: MatCholeskyFactor - Performs in-place Cholesky factorization of a
3161: symmetric matrix.
3163: Collective on mat
3165: Input Parameters:
3166: + mat - the matrix
3167: . perm - row and column permutations
3168: - f - expected fill as ratio of original fill
3170: Notes:
3171: See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`,
3172: `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3174: Most users should employ the `KSP` interface for linear solvers
3175: instead of working directly with matrix algebra routines such as this.
3176: See, e.g., `KSPCreate()`.
3178: Level: developer
3180: Developer Note:
3181: The Fortran interface is not autogenerated as the f90
3182: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3184: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3185: `MatGetOrdering()`
3186: @*/
3187: PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3188: {
3189: MatFactorInfo tinfo;
3198: MatCheckPreallocated(mat, 1);
3199: if (!info) {
3200: MatFactorInfoInitialize(&tinfo);
3201: info = &tinfo;
3202: }
3204: PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0);
3205: PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3206: PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0);
3207: PetscObjectStateIncrease((PetscObject)mat);
3208: return 0;
3209: }
3211: /*@C
3212: MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3213: of a symmetric matrix.
3215: Collective on fact
3217: Input Parameters:
3218: + fact - the factor matrix obtained with `MatGetFactor()`
3219: . mat - the matrix
3220: . perm - row and column permutations
3221: - info - options for factorization, includes
3222: $ fill - expected fill as ratio of original fill.
3223: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3224: $ Run with the option -info to determine an optimal value to use
3226: Notes:
3227: See `MatLUFactorSymbolic()` for the nonsymmetric case. See also
3228: `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3230: Most users should employ the `KSP` interface for linear solvers
3231: instead of working directly with matrix algebra routines such as this.
3232: See, e.g., `KSPCreate()`.
3234: Level: developer
3236: Developer Note:
3237: The Fortran interface is not autogenerated as the f90
3238: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3240: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3241: `MatGetOrdering()`
3242: @*/
3243: PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3244: {
3245: MatFactorInfo tinfo;
3255: if (!(fact)->ops->choleskyfactorsymbolic) {
3256: MatSolverType stype;
3257: MatFactorGetSolverType(fact, &stype);
3258: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3259: }
3260: MatCheckPreallocated(mat, 2);
3261: if (!info) {
3262: MatFactorInfoInitialize(&tinfo);
3263: info = &tinfo;
3264: }
3266: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3267: (fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info);
3268: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3269: PetscObjectStateIncrease((PetscObject)fact);
3270: return 0;
3271: }
3273: /*@C
3274: MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3275: of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3276: `MatCholeskyFactorSymbolic()`.
3278: Collective on fact
3280: Input Parameters:
3281: + fact - the factor matrix obtained with `MatGetFactor()`
3282: . mat - the initial matrix
3283: . info - options for factorization
3284: - fact - the symbolic factor of mat
3286: Note:
3287: Most users should employ the `KSP` interface for linear solvers
3288: instead of working directly with matrix algebra routines such as this.
3289: See, e.g., `KSPCreate()`.
3291: Level: developer
3293: Developer Note:
3294: The Fortran interface is not autogenerated as the f90
3295: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3297: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3298: @*/
3299: PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3300: {
3301: MatFactorInfo tinfo;
3310: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3311: MatCheckPreallocated(mat, 2);
3312: if (!info) {
3313: MatFactorInfoInitialize(&tinfo);
3314: info = &tinfo;
3315: }
3317: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3318: else PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0);
3319: (fact->ops->choleskyfactornumeric)(fact, mat, info);
3320: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3321: else PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0);
3322: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3323: PetscObjectStateIncrease((PetscObject)fact);
3324: return 0;
3325: }
3327: /*@
3328: MatQRFactor - Performs in-place QR factorization of matrix.
3330: Collective on mat
3332: Input Parameters:
3333: + mat - the matrix
3334: . col - column permutation
3335: - info - options for factorization, includes
3336: $ fill - expected fill as ratio of original fill.
3337: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3338: $ Run with the option -info to determine an optimal value to use
3340: Notes:
3341: Most users should employ the `KSP` interface for linear solvers
3342: instead of working directly with matrix algebra routines such as this.
3343: See, e.g., `KSPCreate()`.
3345: This changes the state of the matrix to a factored matrix; it cannot be used
3346: for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3348: Level: developer
3350: Developer Note:
3351: The Fortran interface is not autogenerated as the f90
3352: interface definition cannot be generated correctly [due to MatFactorInfo]
3354: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3355: `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3356: @*/
3357: PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3358: {
3365: MatCheckPreallocated(mat, 1);
3366: PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0);
3367: PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3368: PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0);
3369: PetscObjectStateIncrease((PetscObject)mat);
3370: return 0;
3371: }
3373: /*@
3374: MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3375: Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3377: Collective on fact
3379: Input Parameters:
3380: + fact - the factor matrix obtained with `MatGetFactor()`
3381: . mat - the matrix
3382: . col - column permutation
3383: - info - options for factorization, includes
3384: $ fill - expected fill as ratio of original fill.
3385: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3386: $ Run with the option -info to determine an optimal value to use
3388: Most users should employ the `KSP` interface for linear solvers
3389: instead of working directly with matrix algebra routines such as this.
3390: See, e.g., `KSPCreate()`.
3392: Level: developer
3394: Developer Note:
3395: The Fortran interface is not autogenerated as the f90
3396: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3398: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3399: @*/
3400: PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3401: {
3402: MatFactorInfo tinfo;
3411: MatCheckPreallocated(mat, 2);
3412: if (!info) {
3413: MatFactorInfoInitialize(&tinfo);
3414: info = &tinfo;
3415: }
3417: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0);
3418: PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3419: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0);
3420: PetscObjectStateIncrease((PetscObject)fact);
3421: return 0;
3422: }
3424: /*@
3425: MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3426: Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3428: Collective on fact
3430: Input Parameters:
3431: + fact - the factor matrix obtained with `MatGetFactor()`
3432: . mat - the matrix
3433: - info - options for factorization
3435: Notes:
3436: See `MatQRFactor()` for in-place factorization.
3438: Most users should employ the `KSP` interface for linear solvers
3439: instead of working directly with matrix algebra routines such as this.
3440: See, e.g., `KSPCreate()`.
3442: Level: developer
3444: Developer Note:
3445: The Fortran interface is not autogenerated as the f90
3446: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3448: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3449: @*/
3450: PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3451: {
3452: MatFactorInfo tinfo;
3460: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3462: MatCheckPreallocated(mat, 2);
3463: if (!info) {
3464: MatFactorInfoInitialize(&tinfo);
3465: info = &tinfo;
3466: }
3468: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0);
3469: else PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0);
3470: PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3471: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0);
3472: else PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0);
3473: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3474: PetscObjectStateIncrease((PetscObject)fact);
3475: return 0;
3476: }
3478: /* ----------------------------------------------------------------*/
3479: /*@
3480: MatSolve - Solves A x = b, given a factored matrix.
3482: Neighbor-wise Collective on mat
3484: Input Parameters:
3485: + mat - the factored matrix
3486: - b - the right-hand-side vector
3488: Output Parameter:
3489: . x - the result vector
3491: Notes:
3492: The vectors b and x cannot be the same. I.e., one cannot
3493: call `MatSolve`(A,x,x).
3495: Most users should employ the `KSP` interface for linear solvers
3496: instead of working directly with matrix algebra routines such as this.
3497: See, e.g., `KSPCreate()`.
3499: Level: developer
3501: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3502: @*/
3503: PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3504: {
3515: if (!mat->rmap->N && !mat->cmap->N) return 0;
3516: MatCheckPreallocated(mat, 1);
3518: PetscLogEventBegin(MAT_Solve, mat, b, x, 0);
3519: if (mat->factorerrortype) {
3520: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3521: VecSetInf(x);
3522: } else PetscUseTypeMethod(mat, solve, b, x);
3523: PetscLogEventEnd(MAT_Solve, mat, b, x, 0);
3524: PetscObjectStateIncrease((PetscObject)x);
3525: return 0;
3526: }
3528: static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3529: {
3530: Vec b, x;
3531: PetscInt N, i;
3532: PetscErrorCode (*f)(Mat, Vec, Vec);
3533: PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3535: if (A->factorerrortype) {
3536: PetscInfo(A, "MatFactorError %d\n", A->factorerrortype);
3537: MatSetInf(X);
3538: return 0;
3539: }
3540: f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3542: MatBoundToCPU(A, &Abound);
3543: if (!Abound) {
3544: PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "");
3545: PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "");
3546: }
3547: #if defined(PETSC_HAVE_CUDA)
3548: if (Bneedconv) MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B);
3549: if (Xneedconv) MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X);
3550: #elif (PETSC_HAVE_HIP)
3551: if (Bneedconv) MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B);
3552: if (Xneedconv) MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X);
3553: #endif
3554: MatGetSize(B, NULL, &N);
3555: for (i = 0; i < N; i++) {
3556: MatDenseGetColumnVecRead(B, i, &b);
3557: MatDenseGetColumnVecWrite(X, i, &x);
3558: (*f)(A, b, x);
3559: MatDenseRestoreColumnVecWrite(X, i, &x);
3560: MatDenseRestoreColumnVecRead(B, i, &b);
3561: }
3562: if (Bneedconv) MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B);
3563: if (Xneedconv) MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X);
3564: return 0;
3565: }
3567: /*@
3568: MatMatSolve - Solves A X = B, given a factored matrix.
3570: Neighbor-wise Collective on A
3572: Input Parameters:
3573: + A - the factored matrix
3574: - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3576: Output Parameter:
3577: . X - the result matrix (dense matrix)
3579: Note:
3580: If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO;
3581: otherwise, B and X cannot be the same.
3583: Level: developer
3585: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3586: @*/
3587: PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3588: {
3598: if (!A->rmap->N && !A->cmap->N) return 0;
3600: MatCheckPreallocated(A, 1);
3602: PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3603: if (!A->ops->matsolve) {
3604: PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name);
3605: MatMatSolve_Basic(A, B, X, PETSC_FALSE);
3606: } else PetscUseTypeMethod(A, matsolve, B, X);
3607: PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3608: PetscObjectStateIncrease((PetscObject)X);
3609: return 0;
3610: }
3612: /*@
3613: MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3615: Neighbor-wise Collective on A
3617: Input Parameters:
3618: + A - the factored matrix
3619: - B - the right-hand-side matrix (`MATDENSE` matrix)
3621: Output Parameter:
3622: . X - the result matrix (dense matrix)
3624: Note:
3625: The matrices B and X cannot be the same. I.e., one cannot
3626: call `MatMatSolveTranspose`(A,X,X).
3628: Level: developer
3630: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3631: @*/
3632: PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3633: {
3645: if (!A->rmap->N && !A->cmap->N) return 0;
3647: MatCheckPreallocated(A, 1);
3649: PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3650: if (!A->ops->matsolvetranspose) {
3651: PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name);
3652: MatMatSolve_Basic(A, B, X, PETSC_TRUE);
3653: } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3654: PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3655: PetscObjectStateIncrease((PetscObject)X);
3656: return 0;
3657: }
3659: /*@
3660: MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3662: Neighbor-wise Collective on A
3664: Input Parameters:
3665: + A - the factored matrix
3666: - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3668: Output Parameter:
3669: . X - the result matrix (dense matrix)
3671: Note:
3672: 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
3673: format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3675: Level: developer
3677: .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3678: @*/
3679: PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3680: {
3692: if (!A->rmap->N && !A->cmap->N) return 0;
3694: MatCheckPreallocated(A, 1);
3696: PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0);
3697: PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3698: PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0);
3699: PetscObjectStateIncrease((PetscObject)X);
3700: return 0;
3701: }
3703: /*@
3704: MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3705: U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3707: Neighbor-wise Collective on mat
3709: Input Parameters:
3710: + mat - the factored matrix
3711: - b - the right-hand-side vector
3713: Output Parameter:
3714: . x - the result vector
3716: Notes:
3717: `MatSolve()` should be used for most applications, as it performs
3718: a forward solve followed by a backward solve.
3720: The vectors b and x cannot be the same, i.e., one cannot
3721: call `MatForwardSolve`(A,x,x).
3723: For matrix in `MATSEQBAIJ` format with block size larger than 1,
3724: the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3725: `MatForwardSolve()` solves U^T*D y = b, and
3726: `MatBackwardSolve()` solves U x = y.
3727: Thus they do not provide a symmetric preconditioner.
3729: Level: developer
3731: .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3732: @*/
3733: PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3734: {
3745: if (!mat->rmap->N && !mat->cmap->N) return 0;
3746: MatCheckPreallocated(mat, 1);
3748: PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0);
3749: PetscUseTypeMethod(mat, forwardsolve, b, x);
3750: PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0);
3751: PetscObjectStateIncrease((PetscObject)x);
3752: return 0;
3753: }
3755: /*@
3756: MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3757: D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3759: Neighbor-wise Collective on mat
3761: Input Parameters:
3762: + mat - the factored matrix
3763: - b - the right-hand-side vector
3765: Output Parameter:
3766: . x - the result vector
3768: Notes:
3769: `MatSolve()` should be used for most applications, as it performs
3770: a forward solve followed by a backward solve.
3772: The vectors b and x cannot be the same. I.e., one cannot
3773: call `MatBackwardSolve`(A,x,x).
3775: For matrix in `MATSEQBAIJ` format with block size larger than 1,
3776: the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3777: `MatForwardSolve()` solves U^T*D y = b, and
3778: `MatBackwardSolve()` solves U x = y.
3779: Thus they do not provide a symmetric preconditioner.
3781: Level: developer
3783: .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3784: @*/
3785: PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3786: {
3797: if (!mat->rmap->N && !mat->cmap->N) return 0;
3798: MatCheckPreallocated(mat, 1);
3800: PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0);
3801: PetscUseTypeMethod(mat, backwardsolve, b, x);
3802: PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0);
3803: PetscObjectStateIncrease((PetscObject)x);
3804: return 0;
3805: }
3807: /*@
3808: MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3810: Neighbor-wise Collective on mat
3812: Input Parameters:
3813: + mat - the factored matrix
3814: . b - the right-hand-side vector
3815: - y - the vector to be added to
3817: Output Parameter:
3818: . x - the result vector
3820: Note:
3821: The vectors b and x cannot be the same. I.e., one cannot
3822: call `MatSolveAdd`(A,x,y,x).
3824: Level: developer
3826: .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3827: @*/
3828: PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3829: {
3830: PetscScalar one = 1.0;
3831: Vec tmp;
3847: if (!mat->rmap->N && !mat->cmap->N) return 0;
3848: MatCheckPreallocated(mat, 1);
3850: PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y);
3851: if (mat->factorerrortype) {
3852: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3853: VecSetInf(x);
3854: } else if (mat->ops->solveadd) {
3855: PetscUseTypeMethod(mat, solveadd, b, y, x);
3856: } else {
3857: /* do the solve then the add manually */
3858: if (x != y) {
3859: MatSolve(mat, b, x);
3860: VecAXPY(x, one, y);
3861: } else {
3862: VecDuplicate(x, &tmp);
3863: VecCopy(x, tmp);
3864: MatSolve(mat, b, x);
3865: VecAXPY(x, one, tmp);
3866: VecDestroy(&tmp);
3867: }
3868: }
3869: PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y);
3870: PetscObjectStateIncrease((PetscObject)x);
3871: return 0;
3872: }
3874: /*@
3875: MatSolveTranspose - Solves A' x = b, given a factored matrix.
3877: Neighbor-wise Collective on mat
3879: Input Parameters:
3880: + mat - the factored matrix
3881: - b - the right-hand-side vector
3883: Output Parameter:
3884: . x - the result vector
3886: Notes:
3887: The vectors b and x cannot be the same. I.e., one cannot
3888: call `MatSolveTranspose`(A,x,x).
3890: Most users should employ the `KSP` interface for linear solvers
3891: instead of working directly with matrix algebra routines such as this.
3892: See, e.g., `KSPCreate()`.
3894: Level: developer
3896: .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3897: @*/
3898: PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3899: {
3900: PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3911: if (!mat->rmap->N && !mat->cmap->N) return 0;
3912: MatCheckPreallocated(mat, 1);
3913: PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0);
3914: if (mat->factorerrortype) {
3915: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3916: VecSetInf(x);
3917: } else {
3919: (*f)(mat, b, x);
3920: }
3921: PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0);
3922: PetscObjectStateIncrease((PetscObject)x);
3923: return 0;
3924: }
3926: /*@
3927: MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3928: factored matrix.
3930: Neighbor-wise Collective on mat
3932: Input Parameters:
3933: + mat - the factored matrix
3934: . b - the right-hand-side vector
3935: - y - the vector to be added to
3937: Output Parameter:
3938: . x - the result vector
3940: Note:
3941: The vectors b and x cannot be the same. I.e., one cannot
3942: call `MatSolveTransposeAdd`(A,x,y,x).
3944: Level: developer
3946: .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
3947: @*/
3948: PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
3949: {
3950: PetscScalar one = 1.0;
3951: Vec tmp;
3952: PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
3967: if (!mat->rmap->N && !mat->cmap->N) return 0;
3968: MatCheckPreallocated(mat, 1);
3970: PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y);
3971: if (mat->factorerrortype) {
3972: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3973: VecSetInf(x);
3974: } else if (f) {
3975: (*f)(mat, b, y, x);
3976: } else {
3977: /* do the solve then the add manually */
3978: if (x != y) {
3979: MatSolveTranspose(mat, b, x);
3980: VecAXPY(x, one, y);
3981: } else {
3982: VecDuplicate(x, &tmp);
3983: VecCopy(x, tmp);
3984: MatSolveTranspose(mat, b, x);
3985: VecAXPY(x, one, tmp);
3986: VecDestroy(&tmp);
3987: }
3988: }
3989: PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y);
3990: PetscObjectStateIncrease((PetscObject)x);
3991: return 0;
3992: }
3993: /* ----------------------------------------------------------------*/
3995: /*@
3996: MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
3998: Neighbor-wise Collective on mat
4000: Input Parameters:
4001: + mat - the matrix
4002: . b - the right hand side
4003: . omega - the relaxation factor
4004: . flag - flag indicating the type of SOR (see below)
4005: . shift - diagonal shift
4006: . its - the number of iterations
4007: - lits - the number of local iterations
4009: Output Parameter:
4010: . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4012: SOR Flags:
4013: + `SOR_FORWARD_SWEEP` - forward SOR
4014: . `SOR_BACKWARD_SWEEP` - backward SOR
4015: . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4016: . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4017: . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4018: . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4019: . `SOR_EISENSTAT` - SOR with Eisenstat trick
4020: . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4021: upper/lower triangular part of matrix to
4022: vector (with omega)
4023: - `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4025: Notes:
4026: `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4027: `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4028: on each processor.
4030: Application programmers will not generally use `MatSOR()` directly,
4031: but instead will employ the `KSP`/`PC` interface.
4033: For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4035: Most users should employ the `KSP` interface for linear solvers
4036: instead of working directly with matrix algebra routines such as this.
4037: See, e.g., `KSPCreate()`.
4039: Vectors x and b CANNOT be the same
4041: Notes for Advanced Users:
4042: The flags are implemented as bitwise inclusive or operations.
4043: For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4044: to specify a zero initial guess for SSOR.
4046: Developer Note:
4047: We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4049: Level: developer
4051: .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4052: @*/
4053: PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4054: {
4070: MatCheckPreallocated(mat, 1);
4071: PetscLogEventBegin(MAT_SOR, mat, b, x, 0);
4072: PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4073: PetscLogEventEnd(MAT_SOR, mat, b, x, 0);
4074: PetscObjectStateIncrease((PetscObject)x);
4075: return 0;
4076: }
4078: /*
4079: Default matrix copy routine.
4080: */
4081: PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4082: {
4083: PetscInt i, rstart = 0, rend = 0, nz;
4084: const PetscInt *cwork;
4085: const PetscScalar *vwork;
4087: if (B->assembled) MatZeroEntries(B);
4088: if (str == SAME_NONZERO_PATTERN) {
4089: MatGetOwnershipRange(A, &rstart, &rend);
4090: for (i = rstart; i < rend; i++) {
4091: MatGetRow(A, i, &nz, &cwork, &vwork);
4092: MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES);
4093: MatRestoreRow(A, i, &nz, &cwork, &vwork);
4094: }
4095: } else {
4096: MatAYPX(B, 0.0, A, str);
4097: }
4098: MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);
4099: MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);
4100: return 0;
4101: }
4103: /*@
4104: MatCopy - Copies a matrix to another matrix.
4106: Collective on A
4108: Input Parameters:
4109: + A - the matrix
4110: - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4112: Output Parameter:
4113: . B - where the copy is put
4115: Notes:
4116: If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4118: `MatCopy()` copies the matrix entries of a matrix to another existing
4119: matrix (after first zeroing the second matrix). A related routine is
4120: `MatConvert()`, which first creates a new matrix and then copies the data.
4122: Level: intermediate
4124: .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4125: @*/
4126: PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4127: {
4128: PetscInt i;
4135: MatCheckPreallocated(B, 2);
4139: A->cmap->N, B->cmap->N);
4140: MatCheckPreallocated(A, 1);
4141: if (A == B) return 0;
4143: PetscLogEventBegin(MAT_Copy, A, B, 0, 0);
4144: if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4145: else MatCopy_Basic(A, B, str);
4147: B->stencil.dim = A->stencil.dim;
4148: B->stencil.noc = A->stencil.noc;
4149: for (i = 0; i <= A->stencil.dim; i++) {
4150: B->stencil.dims[i] = A->stencil.dims[i];
4151: B->stencil.starts[i] = A->stencil.starts[i];
4152: }
4154: PetscLogEventEnd(MAT_Copy, A, B, 0, 0);
4155: PetscObjectStateIncrease((PetscObject)B);
4156: return 0;
4157: }
4159: /*@C
4160: MatConvert - Converts a matrix to another matrix, either of the same
4161: or different type.
4163: Collective on mat
4165: Input Parameters:
4166: + mat - the matrix
4167: . newtype - new matrix type. Use `MATSAME` to create a new matrix of the
4168: same type as the original matrix.
4169: - reuse - denotes if the destination matrix is to be created or reused.
4170: 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
4171: `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).
4173: Output Parameter:
4174: . M - pointer to place new matrix
4176: Notes:
4177: `MatConvert()` first creates a new matrix and then copies the data from
4178: the first matrix. A related routine is `MatCopy()`, which copies the matrix
4179: entries of one matrix to another already existing matrix context.
4181: Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4182: the MPI communicator of the generated matrix is always the same as the communicator
4183: of the input matrix.
4185: Level: intermediate
4187: .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4188: @*/
4189: PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4190: {
4191: PetscBool sametype, issame, flg;
4192: PetscBool3 issymmetric, ishermitian;
4193: char convname[256], mtype[256];
4194: Mat B;
4201: MatCheckPreallocated(mat, 1);
4203: PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg);
4204: if (flg) newtype = mtype;
4206: PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype);
4207: PetscStrcmp(newtype, "same", &issame);
4211: if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4212: PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4213: return 0;
4214: }
4216: /* Cache Mat options because some converters use MatHeaderReplace */
4217: issymmetric = mat->symmetric;
4218: ishermitian = mat->hermitian;
4220: if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4221: PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4222: PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4223: } else {
4224: PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4225: const char *prefix[3] = {"seq", "mpi", ""};
4226: PetscInt i;
4227: /*
4228: Order of precedence:
4229: 0) See if newtype is a superclass of the current matrix.
4230: 1) See if a specialized converter is known to the current matrix.
4231: 2) See if a specialized converter is known to the desired matrix class.
4232: 3) See if a good general converter is registered for the desired class
4233: (as of 6/27/03 only MATMPIADJ falls into this category).
4234: 4) See if a good general converter is known for the current matrix.
4235: 5) Use a really basic converter.
4236: */
4238: /* 0) See if newtype is a superclass of the current matrix.
4239: i.e mat is mpiaij and newtype is aij */
4240: for (i = 0; i < 2; i++) {
4241: PetscStrncpy(convname, prefix[i], sizeof(convname));
4242: PetscStrlcat(convname, newtype, sizeof(convname));
4243: PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg);
4244: PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg);
4245: if (flg) {
4246: if (reuse == MAT_INPLACE_MATRIX) {
4247: PetscInfo(mat, "Early return\n");
4248: return 0;
4249: } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4250: PetscInfo(mat, "Calling MatDuplicate\n");
4251: PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4252: return 0;
4253: } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4254: PetscInfo(mat, "Calling MatCopy\n");
4255: MatCopy(mat, *M, SAME_NONZERO_PATTERN);
4256: return 0;
4257: }
4258: }
4259: }
4260: /* 1) See if a specialized converter is known to the current matrix and the desired class */
4261: for (i = 0; i < 3; i++) {
4262: PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4263: PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4264: PetscStrlcat(convname, "_", sizeof(convname));
4265: PetscStrlcat(convname, prefix[i], sizeof(convname));
4266: PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname));
4267: PetscStrlcat(convname, "_C", sizeof(convname));
4268: PetscObjectQueryFunction((PetscObject)mat, convname, &conv);
4269: PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv);
4270: if (conv) goto foundconv;
4271: }
4273: /* 2) See if a specialized converter is known to the desired matrix class. */
4274: MatCreate(PetscObjectComm((PetscObject)mat), &B);
4275: MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
4276: MatSetType(B, newtype);
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, newtype, sizeof(convname));
4283: PetscStrlcat(convname, "_C", sizeof(convname));
4284: PetscObjectQueryFunction((PetscObject)B, convname, &conv);
4285: PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv);
4286: if (conv) {
4287: MatDestroy(&B);
4288: goto foundconv;
4289: }
4290: }
4292: /* 3) See if a good general converter is registered for the desired class */
4293: conv = B->ops->convertfrom;
4294: PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv);
4295: MatDestroy(&B);
4296: if (conv) goto foundconv;
4298: /* 4) See if a good general converter is known for the current matrix */
4299: if (mat->ops->convert) conv = mat->ops->convert;
4300: PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv);
4301: if (conv) goto foundconv;
4303: /* 5) Use a really basic converter. */
4304: PetscInfo(mat, "Using MatConvert_Basic\n");
4305: conv = MatConvert_Basic;
4307: foundconv:
4308: PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4309: (*conv)(mat, newtype, reuse, M);
4310: if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4311: /* the block sizes must be same if the mappings are copied over */
4312: (*M)->rmap->bs = mat->rmap->bs;
4313: (*M)->cmap->bs = mat->cmap->bs;
4314: PetscObjectReference((PetscObject)mat->rmap->mapping);
4315: PetscObjectReference((PetscObject)mat->cmap->mapping);
4316: (*M)->rmap->mapping = mat->rmap->mapping;
4317: (*M)->cmap->mapping = mat->cmap->mapping;
4318: }
4319: (*M)->stencil.dim = mat->stencil.dim;
4320: (*M)->stencil.noc = mat->stencil.noc;
4321: for (i = 0; i <= mat->stencil.dim; i++) {
4322: (*M)->stencil.dims[i] = mat->stencil.dims[i];
4323: (*M)->stencil.starts[i] = mat->stencil.starts[i];
4324: }
4325: PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4326: }
4327: PetscObjectStateIncrease((PetscObject)*M);
4329: /* Copy Mat options */
4330: if (issymmetric == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE);
4331: else if (issymmetric == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE);
4332: if (ishermitian == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE);
4333: else if (ishermitian == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE);
4334: return 0;
4335: }
4337: /*@C
4338: MatFactorGetSolverType - Returns name of the package providing the factorization routines
4340: Not Collective
4342: Input Parameter:
4343: . mat - the matrix, must be a factored matrix
4345: Output Parameter:
4346: . type - the string name of the package (do not free this string)
4348: Note:
4349: In Fortran you pass in a empty string and the package name will be copied into it.
4350: (Make sure the string is long enough)
4352: Level: intermediate
4354: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4355: @*/
4356: PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4357: {
4358: PetscErrorCode (*conv)(Mat, MatSolverType *);
4364: PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv);
4365: if (conv) (*conv)(mat, type);
4366: else *type = MATSOLVERPETSC;
4367: return 0;
4368: }
4370: typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4371: struct _MatSolverTypeForSpecifcType {
4372: MatType mtype;
4373: /* no entry for MAT_FACTOR_NONE */
4374: PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4375: MatSolverTypeForSpecifcType next;
4376: };
4378: typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4379: struct _MatSolverTypeHolder {
4380: char *name;
4381: MatSolverTypeForSpecifcType handlers;
4382: MatSolverTypeHolder next;
4383: };
4385: static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4387: /*@C
4388: MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4390: Input Parameters:
4391: + package - name of the package, for example petsc or superlu
4392: . mtype - the matrix type that works with this package
4393: . ftype - the type of factorization supported by the package
4394: - createfactor - routine that will create the factored matrix ready to be used
4396: Level: developer
4398: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4399: @*/
4400: PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4401: {
4402: MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL;
4403: PetscBool flg;
4404: MatSolverTypeForSpecifcType inext, iprev = NULL;
4406: MatInitializePackage();
4407: if (!next) {
4408: PetscNew(&MatSolverTypeHolders);
4409: PetscStrallocpy(package, &MatSolverTypeHolders->name);
4410: PetscNew(&MatSolverTypeHolders->handlers);
4411: PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype);
4412: MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4413: return 0;
4414: }
4415: while (next) {
4416: PetscStrcasecmp(package, next->name, &flg);
4417: if (flg) {
4419: inext = next->handlers;
4420: while (inext) {
4421: PetscStrcasecmp(mtype, inext->mtype, &flg);
4422: if (flg) {
4423: inext->createfactor[(int)ftype - 1] = createfactor;
4424: return 0;
4425: }
4426: iprev = inext;
4427: inext = inext->next;
4428: }
4429: PetscNew(&iprev->next);
4430: PetscStrallocpy(mtype, (char **)&iprev->next->mtype);
4431: iprev->next->createfactor[(int)ftype - 1] = createfactor;
4432: return 0;
4433: }
4434: prev = next;
4435: next = next->next;
4436: }
4437: PetscNew(&prev->next);
4438: PetscStrallocpy(package, &prev->next->name);
4439: PetscNew(&prev->next->handlers);
4440: PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype);
4441: prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4442: return 0;
4443: }
4445: /*@C
4446: MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4448: Input Parameters:
4449: + type - name of the package, for example petsc or superlu
4450: . ftype - the type of factorization supported by the type
4451: - mtype - the matrix type that works with this type
4453: Output Parameters:
4454: + foundtype - `PETSC_TRUE` if the type was registered
4455: . foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4456: - createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4458: Level: developer
4460: .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4461: @*/
4462: PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4463: {
4464: MatSolverTypeHolder next = MatSolverTypeHolders;
4465: PetscBool flg;
4466: MatSolverTypeForSpecifcType inext;
4468: if (foundtype) *foundtype = PETSC_FALSE;
4469: if (foundmtype) *foundmtype = PETSC_FALSE;
4470: if (createfactor) *createfactor = NULL;
4472: if (type) {
4473: while (next) {
4474: PetscStrcasecmp(type, next->name, &flg);
4475: if (flg) {
4476: if (foundtype) *foundtype = PETSC_TRUE;
4477: inext = next->handlers;
4478: while (inext) {
4479: PetscStrbeginswith(mtype, inext->mtype, &flg);
4480: if (flg) {
4481: if (foundmtype) *foundmtype = PETSC_TRUE;
4482: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4483: return 0;
4484: }
4485: inext = inext->next;
4486: }
4487: }
4488: next = next->next;
4489: }
4490: } else {
4491: while (next) {
4492: inext = next->handlers;
4493: while (inext) {
4494: PetscStrcmp(mtype, inext->mtype, &flg);
4495: if (flg && inext->createfactor[(int)ftype - 1]) {
4496: if (foundtype) *foundtype = PETSC_TRUE;
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: next = next->next;
4504: }
4505: /* try with base classes inext->mtype */
4506: next = MatSolverTypeHolders;
4507: while (next) {
4508: inext = next->handlers;
4509: while (inext) {
4510: PetscStrbeginswith(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: }
4522: return 0;
4523: }
4525: PetscErrorCode MatSolverTypeDestroy(void)
4526: {
4527: MatSolverTypeHolder next = MatSolverTypeHolders, prev;
4528: MatSolverTypeForSpecifcType inext, iprev;
4530: while (next) {
4531: PetscFree(next->name);
4532: inext = next->handlers;
4533: while (inext) {
4534: PetscFree(inext->mtype);
4535: iprev = inext;
4536: inext = inext->next;
4537: PetscFree(iprev);
4538: }
4539: prev = next;
4540: next = next->next;
4541: PetscFree(prev);
4542: }
4543: MatSolverTypeHolders = NULL;
4544: return 0;
4545: }
4547: /*@C
4548: MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4550: Logically Collective on mat
4552: Input Parameters:
4553: . mat - the matrix
4555: Output Parameters:
4556: . flg - `PETSC_TRUE` if uses the ordering
4558: Note:
4559: Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4560: packages do not, thus we want to skip generating the ordering when it is not needed or used.
4562: Level: developer
4564: .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4565: @*/
4566: PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4567: {
4568: *flg = mat->canuseordering;
4569: return 0;
4570: }
4572: /*@C
4573: MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4575: Logically Collective on mat
4577: Input Parameters:
4578: . mat - the matrix obtained with `MatGetFactor()`
4580: Output Parameters:
4581: . otype - the preferred type
4583: Level: developer
4585: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4586: @*/
4587: PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4588: {
4589: *otype = mat->preferredordering[ftype];
4591: return 0;
4592: }
4594: /*@C
4595: MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4597: Collective on mat
4599: Input Parameters:
4600: + mat - the matrix
4601: . type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4602: - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4604: Output Parameters:
4605: . f - the factor matrix used with MatXXFactorSymbolic() calls
4607: Options Database Key:
4608: . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4609: One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4611: Notes:
4612: Users usually access the factorization solvers via `KSP`
4614: Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4615: such as pastix, superlu, mumps etc.
4617: PETSc must have been ./configure to use the external solver, using the option --download-package
4619: Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4620: where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4621: call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix.
4623: Developer Note:
4624: This should actually be called `MatCreateFactor()` since it creates a new factor object
4626: Level: intermediate
4628: .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4629: `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4630: @*/
4631: PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4632: {
4633: PetscBool foundtype, foundmtype;
4634: PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4640: MatCheckPreallocated(mat, 1);
4642: MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv);
4643: if (!foundtype) {
4644: if (type) {
4645: 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],
4646: ((PetscObject)mat)->type_name, type);
4647: } else {
4648: 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);
4649: }
4650: }
4654: (*conv)(mat, ftype, f);
4655: if (mat->factorprefix) MatSetOptionsPrefix(*f, mat->factorprefix);
4656: return 0;
4657: }
4659: /*@C
4660: MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4662: Not Collective
4664: Input Parameters:
4665: + mat - the matrix
4666: . type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4667: - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4669: Output Parameter:
4670: . flg - PETSC_TRUE if the factorization is available
4672: Notes:
4673: Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4674: such as pastix, superlu, mumps etc.
4676: PETSc must have been ./configure to use the external solver, using the option --download-package
4678: Developer Note:
4679: This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4681: Level: intermediate
4683: .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4684: `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4685: @*/
4686: PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4687: {
4688: PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4695: MatCheckPreallocated(mat, 1);
4697: MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv);
4698: *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4699: return 0;
4700: }
4702: /*@
4703: MatDuplicate - Duplicates a matrix including the non-zero structure.
4705: Collective on mat
4707: Input Parameters:
4708: + mat - the matrix
4709: - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4710: See the manual page for `MatDuplicateOption()` for an explanation of these options.
4712: Output Parameter:
4713: . M - pointer to place new matrix
4715: Level: intermediate
4717: Notes:
4718: You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4720: 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.
4722: 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
4723: is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4724: User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4726: .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4727: @*/
4728: PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4729: {
4730: Mat B;
4731: VecType vtype;
4732: PetscInt i;
4733: PetscObject dm;
4734: void (*viewf)(void);
4741: MatCheckPreallocated(mat, 1);
4743: *M = NULL;
4744: PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4745: PetscUseTypeMethod(mat, duplicate, op, M);
4746: PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4747: B = *M;
4749: MatGetOperation(mat, MATOP_VIEW, &viewf);
4750: if (viewf) MatSetOperation(B, MATOP_VIEW, viewf);
4751: MatGetVecType(mat, &vtype);
4752: MatSetVecType(B, vtype);
4754: B->stencil.dim = mat->stencil.dim;
4755: B->stencil.noc = mat->stencil.noc;
4756: for (i = 0; i <= mat->stencil.dim; i++) {
4757: B->stencil.dims[i] = mat->stencil.dims[i];
4758: B->stencil.starts[i] = mat->stencil.starts[i];
4759: }
4761: B->nooffproczerorows = mat->nooffproczerorows;
4762: B->nooffprocentries = mat->nooffprocentries;
4764: PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm);
4765: if (dm) PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm);
4766: PetscObjectStateIncrease((PetscObject)B);
4767: return 0;
4768: }
4770: /*@
4771: MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4773: Logically Collective on mat
4775: Input Parameters:
4776: + mat - the matrix
4777: - v - the vector for storing the diagonal
4779: Output Parameter:
4780: . v - the diagonal of the matrix
4782: Level: intermediate
4784: Note:
4785: Currently only correct in parallel for square matrices.
4787: .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4788: @*/
4789: PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4790: {
4795: MatCheckPreallocated(mat, 1);
4797: PetscUseTypeMethod(mat, getdiagonal, v);
4798: PetscObjectStateIncrease((PetscObject)v);
4799: return 0;
4800: }
4802: /*@C
4803: MatGetRowMin - Gets the minimum value (of the real part) of each
4804: row of the matrix
4806: Logically Collective on mat
4808: Input Parameter:
4809: . mat - the matrix
4811: Output Parameters:
4812: + v - the vector for storing the maximums
4813: - idx - the indices of the column found for each row (optional)
4815: Level: intermediate
4817: Note:
4818: The result of this call are the same as if one converted the matrix to dense format
4819: and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4821: This code is only implemented for a couple of matrix formats.
4823: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4824: `MatGetRowMax()`
4825: @*/
4826: PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4827: {
4833: if (!mat->cmap->N) {
4834: VecSet(v, PETSC_MAX_REAL);
4835: if (idx) {
4836: PetscInt i, m = mat->rmap->n;
4837: for (i = 0; i < m; i++) idx[i] = -1;
4838: }
4839: } else {
4840: MatCheckPreallocated(mat, 1);
4841: }
4842: PetscUseTypeMethod(mat, getrowmin, v, idx);
4843: PetscObjectStateIncrease((PetscObject)v);
4844: return 0;
4845: }
4847: /*@C
4848: MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4849: row of the matrix
4851: Logically Collective on mat
4853: Input Parameter:
4854: . mat - the matrix
4856: Output Parameters:
4857: + v - the vector for storing the minimums
4858: - idx - the indices of the column found for each row (or NULL if not needed)
4860: Level: intermediate
4862: Notes:
4863: if a row is completely empty or has only 0.0 values then the idx[] value for that
4864: row is 0 (the first column).
4866: This code is only implemented for a couple of matrix formats.
4868: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4869: @*/
4870: PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4871: {
4878: if (!mat->cmap->N) {
4879: VecSet(v, 0.0);
4880: if (idx) {
4881: PetscInt i, m = mat->rmap->n;
4882: for (i = 0; i < m; i++) idx[i] = -1;
4883: }
4884: } else {
4885: MatCheckPreallocated(mat, 1);
4886: if (idx) PetscArrayzero(idx, mat->rmap->n);
4887: PetscUseTypeMethod(mat, getrowminabs, v, idx);
4888: }
4889: PetscObjectStateIncrease((PetscObject)v);
4890: return 0;
4891: }
4893: /*@C
4894: MatGetRowMax - Gets the maximum value (of the real part) of each
4895: row of the matrix
4897: Logically Collective on mat
4899: Input Parameter:
4900: . mat - the matrix
4902: Output Parameters:
4903: + v - the vector for storing the maximums
4904: - idx - the indices of the column found for each row (optional)
4906: Level: intermediate
4908: Notes:
4909: The result of this call are the same as if one converted the matrix to dense format
4910: and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4912: This code is only implemented for a couple of matrix formats.
4914: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4915: @*/
4916: PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
4917: {
4923: if (!mat->cmap->N) {
4924: VecSet(v, PETSC_MIN_REAL);
4925: if (idx) {
4926: PetscInt i, m = mat->rmap->n;
4927: for (i = 0; i < m; i++) idx[i] = -1;
4928: }
4929: } else {
4930: MatCheckPreallocated(mat, 1);
4931: PetscUseTypeMethod(mat, getrowmax, v, idx);
4932: }
4933: PetscObjectStateIncrease((PetscObject)v);
4934: return 0;
4935: }
4937: /*@C
4938: MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4939: row of the matrix
4941: Logically Collective on mat
4943: Input Parameter:
4944: . mat - the matrix
4946: Output Parameters:
4947: + v - the vector for storing the maximums
4948: - idx - the indices of the column found for each row (or NULL if not needed)
4950: Level: intermediate
4952: Notes:
4953: if a row is completely empty or has only 0.0 values then the idx[] value for that
4954: row is 0 (the first column).
4956: This code is only implemented for a couple of matrix formats.
4958: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4959: @*/
4960: PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
4961: {
4967: if (!mat->cmap->N) {
4968: VecSet(v, 0.0);
4969: if (idx) {
4970: PetscInt i, m = mat->rmap->n;
4971: for (i = 0; i < m; i++) idx[i] = -1;
4972: }
4973: } else {
4974: MatCheckPreallocated(mat, 1);
4975: if (idx) PetscArrayzero(idx, mat->rmap->n);
4976: PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
4977: }
4978: PetscObjectStateIncrease((PetscObject)v);
4979: return 0;
4980: }
4982: /*@
4983: MatGetRowSum - Gets the sum of each row of the matrix
4985: Logically or Neighborhood Collective on mat
4987: Input Parameters:
4988: . mat - the matrix
4990: Output Parameter:
4991: . v - the vector for storing the sum of rows
4993: Level: intermediate
4995: Notes:
4996: This code is slow since it is not currently specialized for different formats
4998: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
4999: @*/
5000: PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5001: {
5002: Vec ones;
5008: MatCheckPreallocated(mat, 1);
5009: MatCreateVecs(mat, &ones, NULL);
5010: VecSet(ones, 1.);
5011: MatMult(mat, ones, v);
5012: VecDestroy(&ones);
5013: return 0;
5014: }
5016: /*@
5017: MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5018: when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5020: Collective on mat
5022: Input Parameter:
5023: . mat - the matrix to provide the transpose
5025: Output Parameter:
5026: . 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
5028: Level: advanced
5030: Note:
5031: 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
5032: routine allows bypassing that call.
5034: .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5035: @*/
5036: PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5037: {
5038: PetscContainer rB = NULL;
5039: MatParentState *rb = NULL;
5041: PetscNew(&rb);
5042: rb->id = ((PetscObject)mat)->id;
5043: rb->state = 0;
5044: MatGetNonzeroState(mat, &rb->nonzerostate);
5045: PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB);
5046: PetscContainerSetPointer(rB, rb);
5047: PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault);
5048: PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB);
5049: PetscObjectDereference((PetscObject)rB);
5050: return 0;
5051: }
5053: /*@
5054: MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5056: Collective on mat
5058: Input Parameters:
5059: + mat - the matrix to transpose
5060: - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5062: Output Parameter:
5063: . B - the transpose
5065: Notes:
5066: If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5068: `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
5069: transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5071: 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.
5073: Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5075: If mat is unchanged from the last call this function returns immediately without recomputing the result
5077: If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5079: Level: intermediate
5081: .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5082: `MatTransposeSymbolic()`
5083: @*/
5084: PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5085: {
5086: PetscContainer rB = NULL;
5087: MatParentState *rb = NULL;
5095: MatCheckPreallocated(mat, 1);
5096: if (reuse == MAT_REUSE_MATRIX) {
5097: PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5099: PetscContainerGetPointer(rB, (void **)&rb);
5101: if (rb->state == ((PetscObject)mat)->state) return 0;
5102: }
5104: PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0);
5105: if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5106: PetscUseTypeMethod(mat, transpose, reuse, B);
5107: PetscObjectStateIncrease((PetscObject)*B);
5108: }
5109: PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0);
5111: if (reuse == MAT_INITIAL_MATRIX) MatTransposeSetPrecursor(mat, *B);
5112: if (reuse != MAT_INPLACE_MATRIX) {
5113: PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5114: PetscContainerGetPointer(rB, (void **)&rb);
5115: rb->state = ((PetscObject)mat)->state;
5116: rb->nonzerostate = mat->nonzerostate;
5117: }
5118: return 0;
5119: }
5121: /*@
5122: MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5124: Collective on A
5126: Input Parameters:
5127: . A - the matrix to transpose
5129: Output Parameter:
5130: . 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
5131: numerical portion.
5133: Level: intermediate
5135: Note:
5136: This is not supported for many matrix types, use `MatTranspose()` in those cases
5138: .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5139: @*/
5140: PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5141: {
5147: PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0);
5148: (*A->ops->transposesymbolic)(A, B);
5149: PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0);
5151: MatTransposeSetPrecursor(A, *B);
5152: return 0;
5153: }
5155: PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5156: {
5157: PetscContainer rB;
5158: MatParentState *rb;
5164: PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB);
5166: PetscContainerGetPointer(rB, (void **)&rb);
5169: return 0;
5170: }
5172: /*@
5173: MatIsTranspose - Test whether a matrix is another one's transpose,
5174: or its own, in which case it tests symmetry.
5176: Collective on A
5178: Input Parameters:
5179: + A - the matrix to test
5180: - B - the matrix to test against, this can equal the first parameter
5182: Output Parameters:
5183: . flg - the result
5185: Notes:
5186: Only available for `MATAIJ` matrices.
5188: The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5189: test involves parallel copies of the block-offdiagonal parts of the matrix.
5191: Level: intermediate
5193: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5194: @*/
5195: PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5196: {
5197: PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5202: PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f);
5203: PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g);
5204: *flg = PETSC_FALSE;
5205: if (f && g) {
5207: (*f)(A, B, tol, flg);
5208: } else {
5209: MatType mattype;
5211: MatGetType(f ? B : A, &mattype);
5212: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5213: }
5214: return 0;
5215: }
5217: /*@
5218: MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5220: Collective on mat
5222: Input Parameters:
5223: + mat - the matrix to transpose and complex conjugate
5224: - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5226: Output Parameter:
5227: . B - the Hermitian transpose
5229: Level: intermediate
5231: .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5232: @*/
5233: PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5234: {
5235: MatTranspose(mat, reuse, B);
5236: #if defined(PETSC_USE_COMPLEX)
5237: MatConjugate(*B);
5238: #endif
5239: return 0;
5240: }
5242: /*@
5243: MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5245: Collective on A
5247: Input Parameters:
5248: + A - the matrix to test
5249: - B - the matrix to test against, this can equal the first parameter
5251: Output Parameters:
5252: . flg - the result
5254: Notes:
5255: Only available for `MATAIJ` matrices.
5257: The sequential algorithm
5258: has a running time of the order of the number of nonzeros; the parallel
5259: test involves parallel copies of the block-offdiagonal parts of the matrix.
5261: Level: intermediate
5263: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5264: @*/
5265: PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5266: {
5267: PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5272: PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f);
5273: PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g);
5274: if (f && g) {
5276: (*f)(A, B, tol, flg);
5277: }
5278: return 0;
5279: }
5281: /*@
5282: MatPermute - Creates a new matrix with rows and columns permuted from the
5283: original.
5285: Collective on mat
5287: Input Parameters:
5288: + mat - the matrix to permute
5289: . row - row permutation, each processor supplies only the permutation for its rows
5290: - col - column permutation, each processor supplies only the permutation for its columns
5292: Output Parameters:
5293: . B - the permuted matrix
5295: Level: advanced
5297: Note:
5298: The index sets map from row/col of permuted matrix to row/col of original matrix.
5299: The index sets should be on the same communicator as mat and have the same local sizes.
5301: Developer Note:
5302: If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5303: exploit the fact that row and col are permutations, consider implementing the
5304: more general `MatCreateSubMatrix()` instead.
5306: .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5307: @*/
5308: PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5309: {
5320: MatCheckPreallocated(mat, 1);
5322: if (mat->ops->permute) {
5323: PetscUseTypeMethod(mat, permute, row, col, B);
5324: PetscObjectStateIncrease((PetscObject)*B);
5325: } else {
5326: MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B);
5327: }
5328: return 0;
5329: }
5331: /*@
5332: MatEqual - Compares two matrices.
5334: Collective on A
5336: Input Parameters:
5337: + A - the first matrix
5338: - B - the second matrix
5340: Output Parameter:
5341: . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5343: Level: intermediate
5345: .seealso: `Mat`
5346: @*/
5347: PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5348: {
5355: MatCheckPreallocated(A, 1);
5356: MatCheckPreallocated(B, 2);
5360: B->cmap->N);
5361: if (A->ops->equal && A->ops->equal == B->ops->equal) {
5362: PetscUseTypeMethod(A, equal, B, flg);
5363: } else {
5364: MatMultEqual(A, B, 10, flg);
5365: }
5366: return 0;
5367: }
5369: /*@
5370: MatDiagonalScale - Scales a matrix on the left and right by diagonal
5371: matrices that are stored as vectors. Either of the two scaling
5372: matrices can be NULL.
5374: Collective on mat
5376: Input Parameters:
5377: + mat - the matrix to be scaled
5378: . l - the left scaling vector (or NULL)
5379: - r - the right scaling vector (or NULL)
5381: Note:
5382: `MatDiagonalScale()` computes A = LAR, where
5383: L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5384: The L scales the rows of the matrix, the R scales the columns of the matrix.
5386: Level: intermediate
5388: .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5389: @*/
5390: PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5391: {
5394: if (l) {
5397: }
5398: if (r) {
5401: }
5404: MatCheckPreallocated(mat, 1);
5405: if (!l && !r) return 0;
5407: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5408: PetscUseTypeMethod(mat, diagonalscale, l, r);
5409: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5410: PetscObjectStateIncrease((PetscObject)mat);
5411: if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5412: return 0;
5413: }
5415: /*@
5416: MatScale - Scales all elements of a matrix by a given number.
5418: Logically Collective on mat
5420: Input Parameters:
5421: + mat - the matrix to be scaled
5422: - a - the scaling value
5424: Output Parameter:
5425: . mat - the scaled matrix
5427: Level: intermediate
5429: .seealso: `Mat`, `MatDiagonalScale()`
5430: @*/
5431: PetscErrorCode MatScale(Mat mat, PetscScalar a)
5432: {
5439: MatCheckPreallocated(mat, 1);
5441: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5442: if (a != (PetscScalar)1.0) {
5443: PetscUseTypeMethod(mat, scale, a);
5444: PetscObjectStateIncrease((PetscObject)mat);
5445: }
5446: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5447: return 0;
5448: }
5450: /*@
5451: MatNorm - Calculates various norms of a matrix.
5453: Collective on mat
5455: Input Parameters:
5456: + mat - the matrix
5457: - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5459: Output Parameter:
5460: . nrm - the resulting norm
5462: Level: intermediate
5464: .seealso: `Mat`
5465: @*/
5466: PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5467: {
5474: MatCheckPreallocated(mat, 1);
5476: PetscUseTypeMethod(mat, norm, type, nrm);
5477: return 0;
5478: }
5480: /*
5481: This variable is used to prevent counting of MatAssemblyBegin() that
5482: are called from within a MatAssemblyEnd().
5483: */
5484: static PetscInt MatAssemblyEnd_InUse = 0;
5485: /*@
5486: MatAssemblyBegin - Begins assembling the matrix. This routine should
5487: be called after completing all calls to `MatSetValues()`.
5489: Collective on mat
5491: Input Parameters:
5492: + mat - the matrix
5493: - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5495: Notes:
5496: `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to
5497: use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5499: Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5500: in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5501: using the matrix.
5503: ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5504: 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
5505: a global collective operation requiring all processes that share the matrix.
5507: Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5508: out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5509: before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5511: Level: beginner
5513: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5514: @*/
5515: PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5516: {
5519: MatCheckPreallocated(mat, 1);
5521: if (mat->assembled) {
5522: mat->was_assembled = PETSC_TRUE;
5523: mat->assembled = PETSC_FALSE;
5524: }
5526: if (!MatAssemblyEnd_InUse) {
5527: PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0);
5528: PetscTryTypeMethod(mat, assemblybegin, type);
5529: PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0);
5530: } else PetscTryTypeMethod(mat, assemblybegin, type);
5531: return 0;
5532: }
5534: /*@
5535: MatAssembled - Indicates if a matrix has been assembled and is ready for
5536: use; for example, in matrix-vector product.
5538: Not Collective
5540: Input Parameter:
5541: . mat - the matrix
5543: Output Parameter:
5544: . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5546: Level: advanced
5548: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5549: @*/
5550: PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5551: {
5554: *assembled = mat->assembled;
5555: return 0;
5556: }
5558: /*@
5559: MatAssemblyEnd - Completes assembling the matrix. This routine should
5560: be called after `MatAssemblyBegin()`.
5562: Collective on Mat
5564: Input Parameters:
5565: + mat - the matrix
5566: - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5568: Options Database Keys:
5569: + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5570: . -mat_view ::ascii_info_detail - Prints more detailed info
5571: . -mat_view - Prints matrix in ASCII format
5572: . -mat_view ::ascii_matlab - Prints matrix in Matlab format
5573: . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5574: . -display <name> - Sets display name (default is host)
5575: . -draw_pause <sec> - Sets number of seconds to pause after display
5576: . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5577: . -viewer_socket_machine <machine> - Machine to use for socket
5578: . -viewer_socket_port <port> - Port number to use for socket
5579: - -mat_view binary:filename[:append] - Save matrix to file in binary format
5581: Level: beginner
5583: .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5584: @*/
5585: PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5586: {
5587: static PetscInt inassm = 0;
5588: PetscBool flg = PETSC_FALSE;
5593: inassm++;
5594: MatAssemblyEnd_InUse++;
5595: if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5596: PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0);
5597: PetscTryTypeMethod(mat, assemblyend, type);
5598: PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0);
5599: } else PetscTryTypeMethod(mat, assemblyend, type);
5601: /* Flush assembly is not a true assembly */
5602: if (type != MAT_FLUSH_ASSEMBLY) {
5603: if (mat->num_ass) {
5604: if (!mat->symmetry_eternal) {
5605: mat->symmetric = PETSC_BOOL3_UNKNOWN;
5606: mat->hermitian = PETSC_BOOL3_UNKNOWN;
5607: }
5608: if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5609: if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5610: }
5611: mat->num_ass++;
5612: mat->assembled = PETSC_TRUE;
5613: mat->ass_nonzerostate = mat->nonzerostate;
5614: }
5616: mat->insertmode = NOT_SET_VALUES;
5617: MatAssemblyEnd_InUse--;
5618: PetscObjectStateIncrease((PetscObject)mat);
5619: if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5620: MatViewFromOptions(mat, NULL, "-mat_view");
5622: if (mat->checksymmetryonassembly) {
5623: MatIsSymmetric(mat, mat->checksymmetrytol, &flg);
5624: if (flg) {
5625: PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5626: } else {
5627: PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5628: }
5629: }
5630: if (mat->nullsp && mat->checknullspaceonassembly) MatNullSpaceTest(mat->nullsp, mat, NULL);
5631: }
5632: inassm--;
5633: return 0;
5634: }
5636: /*@
5637: MatSetOption - Sets a parameter option for a matrix. Some options
5638: may be specific to certain storage formats. Some options
5639: determine how values will be inserted (or added). Sorted,
5640: row-oriented input will generally assemble the fastest. The default
5641: is row-oriented.
5643: Logically Collective on mat for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5645: Input Parameters:
5646: + mat - the matrix
5647: . option - the option, one of those listed below (and possibly others),
5648: - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5650: Options Describing Matrix Structure:
5651: + `MAT_SPD` - symmetric positive definite
5652: . `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5653: . `MAT_HERMITIAN` - transpose is the complex conjugation
5654: . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5655: . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5656: . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5657: - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5659: These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5660: do not need to be computed (usually at a high cost)
5662: Options For Use with `MatSetValues()`:
5663: Insert a logically dense subblock, which can be
5664: . `MAT_ROW_ORIENTED` - row-oriented (default)
5666: Note these options reflect the data you pass in with `MatSetValues()`; it has
5667: nothing to do with how the data is stored internally in the matrix
5668: data structure.
5670: When (re)assembling a matrix, we can restrict the input for
5671: efficiency/debugging purposes. These options include
5672: + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5673: . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5674: . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5675: . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5676: . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5677: . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5678: any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5679: performance for very large process counts.
5680: - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5681: of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5682: functions, instead sending only neighbor messages.
5684: Notes:
5685: Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5687: Some options are relevant only for particular matrix types and
5688: are thus ignored by others. Other options are not supported by
5689: certain matrix types and will generate an error message if set.
5691: If using a Fortran 77 module to compute a matrix, one may need to
5692: use the column-oriented option (or convert to the row-oriented
5693: format).
5695: `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5696: that would generate a new entry in the nonzero structure is instead
5697: ignored. Thus, if memory has not alredy been allocated for this particular
5698: data, then the insertion is ignored. For dense matrices, in which
5699: the entire array is allocated, no entries are ever ignored.
5700: Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5702: `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5703: that would generate a new entry in the nonzero structure instead produces
5704: 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
5706: `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5707: that would generate a new entry that has not been preallocated will
5708: instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5709: only.) This is a useful flag when debugging matrix memory preallocation.
5710: If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5712: `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5713: other processors should be dropped, rather than stashed.
5714: This is useful if you know that the "owning" processor is also
5715: always generating the correct matrix entries, so that PETSc need
5716: not transfer duplicate entries generated on another processor.
5718: `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5719: searches during matrix assembly. When this flag is set, the hash table
5720: is created during the first matrix assembly. This hash table is
5721: used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5722: to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5723: should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5724: supported by` MATMPIBAIJ` format only.
5726: `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5727: are kept in the nonzero structure
5729: `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5730: a zero location in the matrix
5732: `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5734: `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5735: zero row routines and thus improves performance for very large process counts.
5737: `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5738: part of the matrix (since they should match the upper triangular part).
5740: `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5741: single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5742: with finite difference schemes with non-periodic boundary conditions.
5744: Developer Note:
5745: `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5746: places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5747: to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5748: not changed.
5750: Level: intermediate
5752: .seealso: `MatOption`, `Mat`, `MatGetOption()`
5753: @*/
5754: PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5755: {
5757: if (op > 0) {
5760: }
5764: switch (op) {
5765: case MAT_FORCE_DIAGONAL_ENTRIES:
5766: mat->force_diagonals = flg;
5767: return 0;
5768: case MAT_NO_OFF_PROC_ENTRIES:
5769: mat->nooffprocentries = flg;
5770: return 0;
5771: case MAT_SUBSET_OFF_PROC_ENTRIES:
5772: mat->assembly_subset = flg;
5773: if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5774: #if !defined(PETSC_HAVE_MPIUNI)
5775: MatStashScatterDestroy_BTS(&mat->stash);
5776: #endif
5777: mat->stash.first_assembly_done = PETSC_FALSE;
5778: }
5779: return 0;
5780: case MAT_NO_OFF_PROC_ZERO_ROWS:
5781: mat->nooffproczerorows = flg;
5782: return 0;
5783: case MAT_SPD:
5784: if (flg) {
5785: mat->spd = PETSC_BOOL3_TRUE;
5786: mat->symmetric = PETSC_BOOL3_TRUE;
5787: mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5788: } else {
5789: mat->spd = PETSC_BOOL3_FALSE;
5790: }
5791: break;
5792: case MAT_SYMMETRIC:
5793: mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5794: if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5795: #if !defined(PETSC_USE_COMPLEX)
5796: mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5797: #endif
5798: break;
5799: case MAT_HERMITIAN:
5800: mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5801: if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5802: #if !defined(PETSC_USE_COMPLEX)
5803: mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5804: #endif
5805: break;
5806: case MAT_STRUCTURALLY_SYMMETRIC:
5807: mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5808: break;
5809: case MAT_SYMMETRY_ETERNAL:
5811: mat->symmetry_eternal = flg;
5812: if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5813: break;
5814: case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5816: mat->structural_symmetry_eternal = flg;
5817: break;
5818: case MAT_SPD_ETERNAL:
5820: mat->spd_eternal = flg;
5821: if (flg) {
5822: mat->structural_symmetry_eternal = PETSC_TRUE;
5823: mat->symmetry_eternal = PETSC_TRUE;
5824: }
5825: break;
5826: case MAT_STRUCTURE_ONLY:
5827: mat->structure_only = flg;
5828: break;
5829: case MAT_SORTED_FULL:
5830: mat->sortedfull = flg;
5831: break;
5832: default:
5833: break;
5834: }
5835: PetscTryTypeMethod(mat, setoption, op, flg);
5836: return 0;
5837: }
5839: /*@
5840: MatGetOption - Gets a parameter option that has been set for a matrix.
5842: Logically Collective on mat
5844: Input Parameters:
5845: + mat - the matrix
5846: - option - the option, this only responds to certain options, check the code for which ones
5848: Output Parameter:
5849: . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5851: Notes:
5852: Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5854: Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5855: `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5857: Level: intermediate
5859: .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5860: `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5861: @*/
5862: PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5863: {
5870: switch (op) {
5871: case MAT_NO_OFF_PROC_ENTRIES:
5872: *flg = mat->nooffprocentries;
5873: break;
5874: case MAT_NO_OFF_PROC_ZERO_ROWS:
5875: *flg = mat->nooffproczerorows;
5876: break;
5877: case MAT_SYMMETRIC:
5878: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5879: break;
5880: case MAT_HERMITIAN:
5881: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5882: break;
5883: case MAT_STRUCTURALLY_SYMMETRIC:
5884: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5885: break;
5886: case MAT_SPD:
5887: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
5888: break;
5889: case MAT_SYMMETRY_ETERNAL:
5890: *flg = mat->symmetry_eternal;
5891: break;
5892: case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5893: *flg = mat->symmetry_eternal;
5894: break;
5895: default:
5896: break;
5897: }
5898: return 0;
5899: }
5901: /*@
5902: MatZeroEntries - Zeros all entries of a matrix. For sparse matrices
5903: this routine retains the old nonzero structure.
5905: Logically Collective on mat
5907: Input Parameters:
5908: . mat - the matrix
5910: Level: intermediate
5912: Note:
5913: 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.
5914: See the Performance chapter of the users manual for information on preallocating matrices.
5916: .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
5917: @*/
5918: PetscErrorCode MatZeroEntries(Mat mat)
5919: {
5924: MatCheckPreallocated(mat, 1);
5926: PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0);
5927: PetscUseTypeMethod(mat, zeroentries);
5928: PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0);
5929: PetscObjectStateIncrease((PetscObject)mat);
5930: return 0;
5931: }
5933: /*@
5934: MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5935: of a set of rows and columns of a matrix.
5937: Collective on mat
5939: Input Parameters:
5940: + mat - the matrix
5941: . numRows - the number of rows to remove
5942: . rows - the global row indices
5943: . diag - value put in the diagonal of the eliminated rows
5944: . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5945: - b - optional vector of right hand side, that will be adjusted by provided solution
5947: Notes:
5948: This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5950: For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5951: 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
5953: If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5954: Krylov method to take advantage of the known solution on the zeroed rows.
5956: For the parallel case, all processes that share the matrix (i.e.,
5957: those in the communicator used for matrix creation) MUST call this
5958: routine, regardless of whether any rows being zeroed are owned by
5959: them.
5961: Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5963: Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5964: list only rows local to itself).
5966: The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
5968: Level: intermediate
5970: .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5971: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5972: @*/
5973: PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
5974: {
5980: MatCheckPreallocated(mat, 1);
5982: PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
5983: MatViewFromOptions(mat, NULL, "-mat_view");
5984: PetscObjectStateIncrease((PetscObject)mat);
5985: return 0;
5986: }
5988: /*@
5989: MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5990: of a set of rows and columns of a matrix.
5992: Collective on mat
5994: Input Parameters:
5995: + mat - the matrix
5996: . is - the rows to zero
5997: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5998: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5999: - b - optional vector of right hand side, that will be adjusted by provided solution
6001: Note:
6002: See `MatZeroRowsColumns()` for details on how this routine operates.
6004: Level: intermediate
6006: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6007: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6008: @*/
6009: PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6010: {
6011: PetscInt numRows;
6012: const PetscInt *rows;
6018: ISGetLocalSize(is, &numRows);
6019: ISGetIndices(is, &rows);
6020: MatZeroRowsColumns(mat, numRows, rows, diag, x, b);
6021: ISRestoreIndices(is, &rows);
6022: return 0;
6023: }
6025: /*@
6026: MatZeroRows - Zeros all entries (except possibly the main diagonal)
6027: of a set of rows of a matrix.
6029: Collective on mat
6031: Input Parameters:
6032: + mat - the matrix
6033: . numRows - the number of rows to remove
6034: . rows - the global row indices
6035: . diag - value put in the diagonal of the eliminated rows
6036: . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6037: - b - optional vector of right hand side, that will be adjusted by provided solution
6039: Notes:
6040: This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6042: For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6044: If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6045: Krylov method to take advantage of the known solution on the zeroed rows.
6047: 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)
6048: from the matrix.
6050: Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6051: 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
6052: formats this does not alter the nonzero structure.
6054: If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6055: of the matrix is not changed the values are
6056: merely zeroed.
6058: The user can set a value in the diagonal entry (or for the `MATAIJ` format
6059: formats can optionally remove the main diagonal entry from the
6060: nonzero structure as well, by passing 0.0 as the final argument).
6062: For the parallel case, all processes that share the matrix (i.e.,
6063: those in the communicator used for matrix creation) MUST call this
6064: routine, regardless of whether any rows being zeroed are owned by
6065: them.
6067: Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6068: list only rows local to itself).
6070: You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6071: owns that are to be zeroed. This saves a global synchronization in the implementation.
6073: Level: intermediate
6075: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6076: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6077: @*/
6078: PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6079: {
6085: MatCheckPreallocated(mat, 1);
6087: PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6088: MatViewFromOptions(mat, NULL, "-mat_view");
6089: PetscObjectStateIncrease((PetscObject)mat);
6090: return 0;
6091: }
6093: /*@
6094: MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6095: of a set of rows of a matrix.
6097: Collective on Mat
6099: Input Parameters:
6100: + mat - the matrix
6101: . is - index set of rows to remove (if NULL then no row is removed)
6102: . diag - value put in all diagonals of eliminated rows
6103: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6104: - b - optional vector of right hand side, that will be adjusted by provided solution
6106: Note:
6107: See `MatZeroRows()` for details on how this routine operates.
6109: Level: intermediate
6111: .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6112: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6113: @*/
6114: PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6115: {
6116: PetscInt numRows = 0;
6117: const PetscInt *rows = NULL;
6121: if (is) {
6123: ISGetLocalSize(is, &numRows);
6124: ISGetIndices(is, &rows);
6125: }
6126: MatZeroRows(mat, numRows, rows, diag, x, b);
6127: if (is) ISRestoreIndices(is, &rows);
6128: return 0;
6129: }
6131: /*@
6132: MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6133: of a set of rows of a matrix. These rows must be local to the process.
6135: Collective on mat
6137: Input Parameters:
6138: + mat - the matrix
6139: . numRows - the number of rows to remove
6140: . rows - the grid coordinates (and component number when dof > 1) for matrix rows
6141: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6142: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6143: - b - optional vector of right hand side, that will be adjusted by provided solution
6145: Notes:
6146: See `MatZeroRows()` for details on how this routine operates.
6148: The grid coordinates are across the entire grid, not just the local portion
6150: In Fortran idxm and idxn should be declared as
6151: $ MatStencil idxm(4,m)
6152: and the values inserted using
6153: $ idxm(MatStencil_i,1) = i
6154: $ idxm(MatStencil_j,1) = j
6155: $ idxm(MatStencil_k,1) = k
6156: $ idxm(MatStencil_c,1) = c
6157: etc
6159: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6160: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6161: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6162: `DM_BOUNDARY_PERIODIC` boundary type.
6164: 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
6165: a single value per point) you can skip filling those indices.
6167: Level: intermediate
6169: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6170: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6171: @*/
6172: PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6173: {
6174: PetscInt dim = mat->stencil.dim;
6175: PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc);
6176: PetscInt *dims = mat->stencil.dims + 1;
6177: PetscInt *starts = mat->stencil.starts;
6178: PetscInt *dxm = (PetscInt *)rows;
6179: PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6185: PetscMalloc1(numRows, &jdxm);
6186: for (i = 0; i < numRows; ++i) {
6187: /* Skip unused dimensions (they are ordered k, j, i, c) */
6188: for (j = 0; j < 3 - sdim; ++j) dxm++;
6189: /* Local index in X dir */
6190: tmp = *dxm++ - starts[0];
6191: /* Loop over remaining dimensions */
6192: for (j = 0; j < dim - 1; ++j) {
6193: /* If nonlocal, set index to be negative */
6194: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6195: /* Update local index */
6196: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6197: }
6198: /* Skip component slot if necessary */
6199: if (mat->stencil.noc) dxm++;
6200: /* Local row number */
6201: if (tmp >= 0) jdxm[numNewRows++] = tmp;
6202: }
6203: MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b);
6204: PetscFree(jdxm);
6205: return 0;
6206: }
6208: /*@
6209: MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6210: of a set of rows and columns of a matrix.
6212: Collective on mat
6214: Input Parameters:
6215: + mat - the matrix
6216: . numRows - the number of rows/columns to remove
6217: . rows - the grid coordinates (and component number when dof > 1) for matrix rows
6218: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6219: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6220: - b - optional vector of right hand side, that will be adjusted by provided solution
6222: Notes:
6223: See `MatZeroRowsColumns()` for details on how this routine operates.
6225: The grid coordinates are across the entire grid, not just the local portion
6227: In Fortran idxm and idxn should be declared as
6228: $ MatStencil idxm(4,m)
6229: and the values inserted using
6230: $ idxm(MatStencil_i,1) = i
6231: $ idxm(MatStencil_j,1) = j
6232: $ idxm(MatStencil_k,1) = k
6233: $ idxm(MatStencil_c,1) = c
6234: etc
6236: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6237: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6238: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6239: `DM_BOUNDARY_PERIODIC` boundary type.
6241: 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
6242: a single value per point) you can skip filling those indices.
6244: Level: intermediate
6246: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6247: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6248: @*/
6249: PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6250: {
6251: PetscInt dim = mat->stencil.dim;
6252: PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc);
6253: PetscInt *dims = mat->stencil.dims + 1;
6254: PetscInt *starts = mat->stencil.starts;
6255: PetscInt *dxm = (PetscInt *)rows;
6256: PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6262: PetscMalloc1(numRows, &jdxm);
6263: for (i = 0; i < numRows; ++i) {
6264: /* Skip unused dimensions (they are ordered k, j, i, c) */
6265: for (j = 0; j < 3 - sdim; ++j) dxm++;
6266: /* Local index in X dir */
6267: tmp = *dxm++ - starts[0];
6268: /* Loop over remaining dimensions */
6269: for (j = 0; j < dim - 1; ++j) {
6270: /* If nonlocal, set index to be negative */
6271: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6272: /* Update local index */
6273: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6274: }
6275: /* Skip component slot if necessary */
6276: if (mat->stencil.noc) dxm++;
6277: /* Local row number */
6278: if (tmp >= 0) jdxm[numNewRows++] = tmp;
6279: }
6280: MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b);
6281: PetscFree(jdxm);
6282: return 0;
6283: }
6285: /*@C
6286: MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6287: of a set of rows of a matrix; using local numbering of rows.
6289: Collective on mat
6291: Input Parameters:
6292: + mat - the matrix
6293: . numRows - the number of rows to remove
6294: . rows - the local row indices
6295: . diag - value put in all diagonals of eliminated rows
6296: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6297: - b - optional vector of right hand side, that will be adjusted by provided solution
6299: Notes:
6300: Before calling `MatZeroRowsLocal()`, the user must first set the
6301: local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6303: See `MatZeroRows()` for details on how this routine operates.
6305: Level: intermediate
6307: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6308: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6309: @*/
6310: PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6311: {
6317: MatCheckPreallocated(mat, 1);
6319: if (mat->ops->zerorowslocal) {
6320: PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6321: } else {
6322: IS is, newis;
6323: const PetscInt *newRows;
6326: ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6327: ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis);
6328: ISGetIndices(newis, &newRows);
6329: PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6330: ISRestoreIndices(newis, &newRows);
6331: ISDestroy(&newis);
6332: ISDestroy(&is);
6333: }
6334: PetscObjectStateIncrease((PetscObject)mat);
6335: return 0;
6336: }
6338: /*@
6339: MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6340: of a set of rows of a matrix; using local numbering of rows.
6342: Collective on mat
6344: Input Parameters:
6345: + mat - the matrix
6346: . is - index set of rows to remove
6347: . diag - value put in all diagonals of eliminated rows
6348: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6349: - b - optional vector of right hand side, that will be adjusted by provided solution
6351: Notes:
6352: Before calling `MatZeroRowsLocalIS()`, the user must first set the
6353: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6355: See `MatZeroRows()` for details on how this routine operates.
6357: Level: intermediate
6359: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6360: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6361: @*/
6362: PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6363: {
6364: PetscInt numRows;
6365: const PetscInt *rows;
6372: MatCheckPreallocated(mat, 1);
6374: ISGetLocalSize(is, &numRows);
6375: ISGetIndices(is, &rows);
6376: MatZeroRowsLocal(mat, numRows, rows, diag, x, b);
6377: ISRestoreIndices(is, &rows);
6378: return 0;
6379: }
6381: /*@
6382: MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6383: of a set of rows and columns of a matrix; using local numbering of rows.
6385: Collective on mat
6387: Input Parameters:
6388: + mat - the matrix
6389: . numRows - the number of rows to remove
6390: . rows - the global row indices
6391: . diag - value put in all diagonals of eliminated rows
6392: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6393: - b - optional vector of right hand side, that will be adjusted by provided solution
6395: Notes:
6396: Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6397: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6399: See `MatZeroRowsColumns()` for details on how this routine operates.
6401: Level: intermediate
6403: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6404: `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6405: @*/
6406: PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6407: {
6408: IS is, newis;
6409: const PetscInt *newRows;
6416: MatCheckPreallocated(mat, 1);
6419: ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6420: ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis);
6421: ISGetIndices(newis, &newRows);
6422: PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6423: ISRestoreIndices(newis, &newRows);
6424: ISDestroy(&newis);
6425: ISDestroy(&is);
6426: PetscObjectStateIncrease((PetscObject)mat);
6427: return 0;
6428: }
6430: /*@
6431: MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6432: of a set of rows and columns of a matrix; using local numbering of rows.
6434: Collective on Mat
6436: Input Parameters:
6437: + mat - the matrix
6438: . is - index set of rows to remove
6439: . diag - value put in all diagonals of eliminated rows
6440: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6441: - b - optional vector of right hand side, that will be adjusted by provided solution
6443: Notes:
6444: Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6445: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6447: See `MatZeroRowsColumns()` for details on how this routine operates.
6449: Level: intermediate
6451: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6452: `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6453: @*/
6454: PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6455: {
6456: PetscInt numRows;
6457: const PetscInt *rows;
6464: MatCheckPreallocated(mat, 1);
6466: ISGetLocalSize(is, &numRows);
6467: ISGetIndices(is, &rows);
6468: MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b);
6469: ISRestoreIndices(is, &rows);
6470: return 0;
6471: }
6473: /*@C
6474: MatGetSize - Returns the numbers of rows and columns in a matrix.
6476: Not Collective
6478: Input Parameter:
6479: . mat - the matrix
6481: Output Parameters:
6482: + m - the number of global rows
6483: - n - the number of global columns
6485: Note: both output parameters can be NULL on input.
6487: Level: beginner
6489: .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6490: @*/
6491: PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6492: {
6494: if (m) *m = mat->rmap->N;
6495: if (n) *n = mat->cmap->N;
6496: return 0;
6497: }
6499: /*@C
6500: MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6501: of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6503: Not Collective
6505: Input Parameter:
6506: . mat - the matrix
6508: Output Parameters:
6509: + m - the number of local rows, use `NULL` to not obtain this value
6510: - n - the number of local columns, use `NULL` to not obtain this value
6512: Level: beginner
6514: .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6515: @*/
6516: PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6517: {
6521: if (m) *m = mat->rmap->n;
6522: if (n) *n = mat->cmap->n;
6523: return 0;
6524: }
6526: /*@C
6527: MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6528: this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6530: Not Collective, unless matrix has not been allocated, then collective on mat
6532: Input Parameter:
6533: . mat - the matrix
6535: Output Parameters:
6536: + m - the global index of the first local column, use `NULL` to not obtain this value
6537: - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6539: Level: developer
6541: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6542: @*/
6543: PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6544: {
6549: MatCheckPreallocated(mat, 1);
6550: if (m) *m = mat->cmap->rstart;
6551: if (n) *n = mat->cmap->rend;
6552: return 0;
6553: }
6555: /*@C
6556: MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6557: 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
6558: vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6560: Not Collective
6562: Input Parameter:
6563: . mat - the matrix
6565: Output Parameters:
6566: + m - the global index of the first local row, use `NULL` to not obtain this value
6567: - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6569: Note:
6570: This function requires that the matrix be preallocated. If you have not preallocated, consider using
6571: `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6572: and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6574: Level: beginner
6576: .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6577: `PetscLayout`
6578: @*/
6579: PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6580: {
6585: MatCheckPreallocated(mat, 1);
6586: if (m) *m = mat->rmap->rstart;
6587: if (n) *n = mat->rmap->rend;
6588: return 0;
6589: }
6591: /*@C
6592: MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6593: 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
6594: vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6596: Not Collective, unless matrix has not been allocated, then collective on mat
6598: Input Parameters:
6599: . mat - the matrix
6601: Output Parameters:
6602: . ranges - start of each processors portion plus one more than the total length at the end
6604: Level: beginner
6606: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6607: @*/
6608: PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6609: {
6612: MatCheckPreallocated(mat, 1);
6613: PetscLayoutGetRanges(mat->rmap, ranges);
6614: return 0;
6615: }
6617: /*@C
6618: MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6619: each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6621: Not Collective, unless matrix has not been allocated, then collective on Mat
6623: Input Parameters:
6624: . mat - the matrix
6626: Output Parameters:
6627: . ranges - start of each processors portion plus one more then the total length at the end
6629: Level: beginner
6631: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6632: @*/
6633: PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6634: {
6637: MatCheckPreallocated(mat, 1);
6638: PetscLayoutGetRanges(mat->cmap, ranges);
6639: return 0;
6640: }
6642: /*@C
6643: MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6644: corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6645: is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6647: Not Collective
6649: Input Parameter:
6650: . A - matrix
6652: Output Parameters:
6653: + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6654: - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6656: Level: intermediate
6658: .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6659: @*/
6660: PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6661: {
6662: PetscErrorCode (*f)(Mat, IS *, IS *);
6664: MatCheckPreallocated(A, 1);
6665: PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f);
6666: if (f) {
6667: (*f)(A, rows, cols);
6668: } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6669: if (rows) ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows);
6670: if (cols) ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols);
6671: }
6672: return 0;
6673: }
6675: /*@C
6676: MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6677: Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6678: to complete the factorization.
6680: Collective on fact
6682: Input Parameters:
6683: + fact - the factorized matrix obtained with `MatGetFactor()`
6684: . mat - the matrix
6685: . row - row permutation
6686: . column - column permutation
6687: - info - structure containing
6688: $ levels - number of levels of fill.
6689: $ expected fill - as ratio of original fill.
6690: $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6691: missing diagonal entries)
6693: Output Parameters:
6694: . fact - new matrix that has been symbolically factored
6696: Level: developer
6698: Notes:
6699: See [Matrix Factorization](sec_matfactor) for additional information.
6701: Most users should employ the `KSP` interface for linear solvers
6702: instead of working directly with matrix algebra routines such as this.
6703: See, e.g., `KSPCreate()`.
6705: Uses the definition of level of fill as in Y. Saad, 2003
6707: Developer Note:
6708: The Fortran interface is not autogenerated as the f90
6709: interface definition cannot be generated correctly [due to `MatFactorInfo`]
6711: References:
6712: . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6714: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6715: `MatGetOrdering()`, `MatFactorInfo`
6716: @*/
6717: PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6718: {
6727: if (!fact->ops->ilufactorsymbolic) {
6728: MatSolverType stype;
6729: MatFactorGetSolverType(fact, &stype);
6730: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6731: }
6734: MatCheckPreallocated(mat, 2);
6736: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0);
6737: (fact->ops->ilufactorsymbolic)(fact, mat, row, col, info);
6738: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0);
6739: return 0;
6740: }
6742: /*@C
6743: MatICCFactorSymbolic - Performs symbolic incomplete
6744: Cholesky factorization for a symmetric matrix. Use
6745: `MatCholeskyFactorNumeric()` to complete the factorization.
6747: Collective on fact
6749: Input Parameters:
6750: + fact - the factorized matrix obtained with `MatGetFactor()`
6751: . mat - the matrix to be factored
6752: . perm - row and column permutation
6753: - info - structure containing
6754: $ levels - number of levels of fill.
6755: $ expected fill - as ratio of original fill.
6757: Output Parameter:
6758: . fact - the factored matrix
6760: Level: developer
6762: Notes:
6763: Most users should employ the `KSP` interface for linear solvers
6764: instead of working directly with matrix algebra routines such as this.
6765: See, e.g., `KSPCreate()`.
6767: This uses the definition of level of fill as in Y. Saad, 2003
6769: Developer Note:
6770: The Fortran interface is not autogenerated as the f90
6771: interface definition cannot be generated correctly [due to `MatFactorInfo`]
6773: References:
6774: . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6776: .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6777: @*/
6778: PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6779: {
6788: if (!(fact)->ops->iccfactorsymbolic) {
6789: MatSolverType stype;
6790: MatFactorGetSolverType(fact, &stype);
6791: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6792: }
6794: MatCheckPreallocated(mat, 2);
6796: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6797: (fact->ops->iccfactorsymbolic)(fact, mat, perm, info);
6798: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6799: return 0;
6800: }
6802: /*@C
6803: MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6804: points to an array of valid matrices, they may be reused to store the new
6805: submatrices.
6807: Collective on mat
6809: Input Parameters:
6810: + mat - the matrix
6811: . n - the number of submatrixes to be extracted (on this processor, may be zero)
6812: . irow, icol - index sets of rows and columns to extract
6813: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6815: Output Parameter:
6816: . submat - the array of submatrices
6818: Notes:
6819: `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6820: (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6821: to extract a parallel submatrix.
6823: Some matrix types place restrictions on the row and column
6824: indices, such as that they be sorted or that they be equal to each other.
6826: The index sets may not have duplicate entries.
6828: When extracting submatrices from a parallel matrix, each processor can
6829: form a different submatrix by setting the rows and columns of its
6830: individual index sets according to the local submatrix desired.
6832: When finished using the submatrices, the user should destroy
6833: them with `MatDestroySubMatrices()`.
6835: `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6836: original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6838: This routine creates the matrices in submat; you should NOT create them before
6839: calling it. It also allocates the array of matrix pointers submat.
6841: For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6842: request one row/column in a block, they must request all rows/columns that are in
6843: that block. For example, if the block size is 2 you cannot request just row 0 and
6844: column 0.
6846: Fortran Note:
6847: The Fortran interface is slightly different from that given below; it
6848: requires one to pass in as submat a `Mat` (integer) array of size at least n+1.
6850: Level: advanced
6852: .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6853: @*/
6854: PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6855: {
6856: PetscInt i;
6857: PetscBool eq;
6861: if (n) {
6866: }
6868: if (n && scall == MAT_REUSE_MATRIX) {
6871: }
6874: MatCheckPreallocated(mat, 1);
6875: PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6876: PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6877: PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6878: for (i = 0; i < n; i++) {
6879: (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6880: ISEqualUnsorted(irow[i], icol[i], &eq);
6881: if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6882: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
6883: if (mat->boundtocpu && mat->bindingpropagates) {
6884: MatBindToCPU((*submat)[i], PETSC_TRUE);
6885: MatSetBindingPropagates((*submat)[i], PETSC_TRUE);
6886: }
6887: #endif
6888: }
6889: return 0;
6890: }
6892: /*@C
6893: MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
6895: Collective on mat
6897: Input Parameters:
6898: + mat - the matrix
6899: . n - the number of submatrixes to be extracted
6900: . irow, icol - index sets of rows and columns to extract
6901: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6903: Output Parameter:
6904: . submat - the array of submatrices
6906: Level: advanced
6908: Note:
6909: This is used by `PCGASM`
6911: .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6912: @*/
6913: PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6914: {
6915: PetscInt i;
6916: PetscBool eq;
6920: if (n) {
6925: }
6927: if (n && scall == MAT_REUSE_MATRIX) {
6930: }
6933: MatCheckPreallocated(mat, 1);
6935: PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6936: PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6937: PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6938: for (i = 0; i < n; i++) {
6939: ISEqualUnsorted(irow[i], icol[i], &eq);
6940: if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6941: }
6942: return 0;
6943: }
6945: /*@C
6946: MatDestroyMatrices - Destroys an array of matrices.
6948: Collective on mat
6950: Input Parameters:
6951: + n - the number of local matrices
6952: - mat - the matrices (note that this is a pointer to the array of matrices)
6954: Level: advanced
6956: Note:
6957: Frees not only the matrices, but also the array that contains the matrices
6958: In Fortran will not free the array.
6960: .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6961: @*/
6962: PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
6963: {
6964: PetscInt i;
6966: if (!*mat) return 0;
6970: for (i = 0; i < n; i++) MatDestroy(&(*mat)[i]);
6972: /* memory is allocated even if n = 0 */
6973: PetscFree(*mat);
6974: return 0;
6975: }
6977: /*@C
6978: MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
6980: Collective on mat
6982: Input Parameters:
6983: + n - the number of local matrices
6984: - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
6985: sequence of MatCreateSubMatrices())
6987: Level: advanced
6989: Note:
6990: Frees not only the matrices, but also the array that contains the matrices
6991: In Fortran will not free the array.
6993: .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6994: @*/
6995: PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
6996: {
6997: Mat mat0;
6999: if (!*mat) return 0;
7000: /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7004: mat0 = (*mat)[0];
7005: if (mat0 && mat0->ops->destroysubmatrices) {
7006: (mat0->ops->destroysubmatrices)(n, mat);
7007: } else {
7008: MatDestroyMatrices(n, mat);
7009: }
7010: return 0;
7011: }
7013: /*@C
7014: MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7016: Collective on mat
7018: Input Parameters:
7019: . mat - the matrix
7021: Output Parameter:
7022: . matstruct - the sequential matrix with the nonzero structure of mat
7024: Level: developer
7026: .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7027: @*/
7028: PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7029: {
7035: MatCheckPreallocated(mat, 1);
7037: PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7038: PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7039: PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7040: return 0;
7041: }
7043: /*@C
7044: MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7046: Collective on mat
7048: Input Parameters:
7049: . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7050: sequence of `MatGetSequentialNonzeroStructure()`)
7052: Level: advanced
7054: Note:
7055: Frees not only the matrices, but also the array that contains the matrices
7057: .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7058: @*/
7059: PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7060: {
7062: MatDestroy(mat);
7063: return 0;
7064: }
7066: /*@
7067: MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7068: replaces the index sets by larger ones that represent submatrices with
7069: additional overlap.
7071: Collective on mat
7073: Input Parameters:
7074: + mat - the matrix
7075: . n - the number of index sets
7076: . is - the array of index sets (these index sets will changed during the call)
7077: - ov - the additional overlap requested
7079: Options Database Key:
7080: . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7082: Level: developer
7084: Developer Note:
7085: Any implementation must preserve block sizes. That is: if the row block size and the column block size of mat are equal to bs, then the output index sets must be compatible with bs.
7087: .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7088: @*/
7089: PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7090: {
7091: PetscInt i, bs, cbs;
7097: if (n) {
7100: }
7103: MatCheckPreallocated(mat, 1);
7105: if (!ov || !n) return 0;
7106: PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7107: PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7108: PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7109: MatGetBlockSizes(mat, &bs, &cbs);
7110: if (bs == cbs) {
7111: for (i = 0; i < n; i++) ISSetBlockSize(is[i], bs);
7112: }
7113: return 0;
7114: }
7116: PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7118: /*@
7119: MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7120: a sub communicator, replaces the index sets by larger ones that represent submatrices with
7121: additional overlap.
7123: Collective on mat
7125: Input Parameters:
7126: + mat - the matrix
7127: . n - the number of index sets
7128: . is - the array of index sets (these index sets will changed during the call)
7129: - ov - the additional overlap requested
7131: ` Options Database Key:
7132: . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7134: Level: developer
7136: .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7137: @*/
7138: PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7139: {
7140: PetscInt i;
7145: if (n) {
7148: }
7151: MatCheckPreallocated(mat, 1);
7152: if (!ov) return 0;
7153: PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7154: for (i = 0; i < n; i++) MatIncreaseOverlapSplit_Single(mat, &is[i], ov);
7155: PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7156: return 0;
7157: }
7159: /*@
7160: MatGetBlockSize - Returns the matrix block size.
7162: Not Collective
7164: Input Parameter:
7165: . mat - the matrix
7167: Output Parameter:
7168: . bs - block size
7170: Notes:
7171: Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7173: If the block size has not been set yet this routine returns 1.
7175: Level: intermediate
7177: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7178: @*/
7179: PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7180: {
7183: *bs = PetscAbs(mat->rmap->bs);
7184: return 0;
7185: }
7187: /*@
7188: MatGetBlockSizes - Returns the matrix block row and column sizes.
7190: Not Collective
7192: Input Parameter:
7193: . mat - the matrix
7195: Output Parameters:
7196: + rbs - row block size
7197: - cbs - column block size
7199: Notes:
7200: Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7201: If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7203: If a block size has not been set yet this routine returns 1.
7205: Level: intermediate
7207: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7208: @*/
7209: PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7210: {
7214: if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7215: if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7216: return 0;
7217: }
7219: /*@
7220: MatSetBlockSize - Sets the matrix block size.
7222: Logically Collective on mat
7224: Input Parameters:
7225: + mat - the matrix
7226: - bs - block size
7228: Notes:
7229: Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7230: This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7232: For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7233: is compatible with the matrix local sizes.
7235: Level: intermediate
7237: .seealso: `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7238: @*/
7239: PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7240: {
7243: MatSetBlockSizes(mat, bs, bs);
7244: return 0;
7245: }
7247: typedef struct {
7248: PetscInt n;
7249: IS *is;
7250: Mat *mat;
7251: PetscObjectState nonzerostate;
7252: Mat C;
7253: } EnvelopeData;
7255: static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7256: {
7257: for (PetscInt i = 0; i < edata->n; i++) ISDestroy(&edata->is[i]);
7258: PetscFree(edata->is);
7259: PetscFree(edata);
7260: return 0;
7261: }
7263: /*
7264: MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7265: the sizes of these blocks in the matrix. An individual block may lie over several processes.
7267: Collective on mat
7269: Input Parameter:
7270: . mat - the matrix
7272: Notes:
7273: There can be zeros within the blocks
7275: The blocks can overlap between processes, including laying on more than two processes
7277: .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7278: */
7279: static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7280: {
7281: PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7282: PetscInt *diag, *odiag, sc;
7283: VecScatter scatter;
7284: PetscScalar *seqv;
7285: const PetscScalar *parv;
7286: const PetscInt *ia, *ja;
7287: PetscBool set, flag, done;
7288: Mat AA = mat, A;
7289: MPI_Comm comm;
7290: PetscMPIInt rank, size, tag;
7291: MPI_Status status;
7292: PetscContainer container;
7293: EnvelopeData *edata;
7294: Vec seq, par;
7295: IS isglobal;
7298: MatIsSymmetricKnown(mat, &set, &flag);
7299: if (!set || !flag) {
7300: /* TOO: only needs nonzero structure of transpose */
7301: MatTranspose(mat, MAT_INITIAL_MATRIX, &AA);
7302: MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN);
7303: }
7304: MatAIJGetLocalMat(AA, &A);
7305: MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7308: MatGetLocalSize(mat, &n, NULL);
7309: PetscObjectGetNewTag((PetscObject)mat, &tag);
7310: PetscObjectGetComm((PetscObject)mat, &comm);
7311: MPI_Comm_size(comm, &size);
7312: MPI_Comm_rank(comm, &rank);
7314: PetscMalloc2(n, &sizes, n, &starts);
7316: if (rank > 0) {
7317: MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status);
7318: MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status);
7319: }
7320: MatGetOwnershipRange(mat, &rstart, NULL);
7321: for (i = 0; i < n; i++) {
7322: env = PetscMax(env, ja[ia[i + 1] - 1]);
7323: II = rstart + i;
7324: if (env == II) {
7325: starts[lblocks] = tbs;
7326: sizes[lblocks++] = 1 + II - tbs;
7327: tbs = 1 + II;
7328: }
7329: }
7330: if (rank < size - 1) {
7331: MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm);
7332: MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm);
7333: }
7335: MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7336: if (!set || !flag) MatDestroy(&AA);
7337: MatDestroy(&A);
7339: PetscNew(&edata);
7340: MatGetNonzeroState(mat, &edata->nonzerostate);
7341: edata->n = lblocks;
7342: /* create IS needed for extracting blocks from the original matrix */
7343: PetscMalloc1(lblocks, &edata->is);
7344: for (PetscInt i = 0; i < lblocks; i++) ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]);
7346: /* Create the resulting inverse matrix structure with preallocation information */
7347: MatCreate(PetscObjectComm((PetscObject)mat), &edata->C);
7348: MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
7349: MatSetBlockSizesFromMats(edata->C, mat, mat);
7350: MatSetType(edata->C, MATAIJ);
7352: /* Communicate the start and end of each row, from each block to the correct rank */
7353: /* TODO: Use PetscSF instead of VecScatter */
7354: for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7355: VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq);
7356: VecGetArrayWrite(seq, &seqv);
7357: for (PetscInt i = 0; i < lblocks; i++) {
7358: for (PetscInt j = 0; j < sizes[i]; j++) {
7359: seqv[cnt] = starts[i];
7360: seqv[cnt + 1] = starts[i] + sizes[i];
7361: cnt += 2;
7362: }
7363: }
7364: VecRestoreArrayWrite(seq, &seqv);
7365: MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
7366: sc -= cnt;
7367: VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par);
7368: ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal);
7369: VecScatterCreate(seq, NULL, par, isglobal, &scatter);
7370: ISDestroy(&isglobal);
7371: VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7372: VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7373: VecScatterDestroy(&scatter);
7374: VecDestroy(&seq);
7375: MatGetOwnershipRangeColumn(mat, &cstart, &cend);
7376: PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag);
7377: VecGetArrayRead(par, &parv);
7378: cnt = 0;
7379: MatGetSize(mat, NULL, &n);
7380: for (PetscInt i = 0; i < mat->rmap->n; i++) {
7381: PetscInt start, end, d = 0, od = 0;
7383: start = (PetscInt)PetscRealPart(parv[cnt]);
7384: end = (PetscInt)PetscRealPart(parv[cnt + 1]);
7385: cnt += 2;
7387: if (start < cstart) {
7388: od += cstart - start + n - cend;
7389: d += cend - cstart;
7390: } else if (start < cend) {
7391: od += n - cend;
7392: d += cend - start;
7393: } else od += n - start;
7394: if (end <= cstart) {
7395: od -= cstart - end + n - cend;
7396: d -= cend - cstart;
7397: } else if (end < cend) {
7398: od -= n - cend;
7399: d -= cend - end;
7400: } else od -= n - end;
7402: odiag[i] = od;
7403: diag[i] = d;
7404: }
7405: VecRestoreArrayRead(par, &parv);
7406: VecDestroy(&par);
7407: MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL);
7408: PetscFree2(diag, odiag);
7409: PetscFree2(sizes, starts);
7411: PetscContainerCreate(PETSC_COMM_SELF, &container);
7412: PetscContainerSetPointer(container, edata);
7413: PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy);
7414: PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container);
7415: PetscObjectDereference((PetscObject)container);
7416: return 0;
7417: }
7419: /*@
7420: MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7422: Collective on A
7424: Input Parameters:
7425: . A - the matrix
7427: Output Parameters:
7428: . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set.
7430: Note:
7431: For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7433: Level: advanced
7435: .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7436: @*/
7437: PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7438: {
7439: PetscContainer container;
7440: EnvelopeData *edata;
7441: PetscObjectState nonzerostate;
7443: PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7444: if (!container) {
7445: MatComputeVariableBlockEnvelope(A);
7446: PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7447: }
7448: PetscContainerGetPointer(container, (void **)&edata);
7449: MatGetNonzeroState(A, &nonzerostate);
7453: MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat);
7454: *C = edata->C;
7456: for (PetscInt i = 0; i < edata->n; i++) {
7457: Mat D;
7458: PetscScalar *dvalues;
7460: MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D);
7461: MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE);
7462: MatSeqDenseInvert(D);
7463: MatDenseGetArray(D, &dvalues);
7464: MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES);
7465: MatDestroy(&D);
7466: }
7467: MatDestroySubMatrices(edata->n, &edata->mat);
7468: MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY);
7469: MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY);
7470: return 0;
7471: }
7473: /*@
7474: MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7476: Logically Collective on mat
7478: Input Parameters:
7479: + mat - the matrix
7480: . nblocks - the number of blocks on this process, each block can only exist on a single process
7481: - bsizes - the block sizes
7483: Notes:
7484: Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7486: 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.
7488: Level: intermediate
7490: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7491: `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7492: @*/
7493: PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7494: {
7495: PetscInt i, ncnt = 0, nlocal;
7499: MatGetLocalSize(mat, &nlocal, NULL);
7500: for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7502: PetscFree(mat->bsizes);
7503: mat->nblocks = nblocks;
7504: PetscMalloc1(nblocks, &mat->bsizes);
7505: PetscArraycpy(mat->bsizes, bsizes, nblocks);
7506: return 0;
7507: }
7509: /*@C
7510: MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7512: Logically Collective on mat
7514: Input Parameter:
7515: . mat - the matrix
7517: Output Parameters:
7518: + nblocks - the number of blocks on this process
7519: - bsizes - the block sizes
7521: Fortran Note:
7522: Currently not supported from Fortran
7524: Level: intermediate
7526: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7527: @*/
7528: PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7529: {
7531: *nblocks = mat->nblocks;
7532: *bsizes = mat->bsizes;
7533: return 0;
7534: }
7536: /*@
7537: MatSetBlockSizes - Sets the matrix block row and column sizes.
7539: Logically Collective on mat
7541: Input Parameters:
7542: + mat - the matrix
7543: . rbs - row block size
7544: - cbs - column block size
7546: Notes:
7547: Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7548: If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7549: This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7551: For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7552: are compatible with the matrix local sizes.
7554: The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7556: Level: intermediate
7558: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7559: @*/
7560: PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7561: {
7565: PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7566: if (mat->rmap->refcnt) {
7567: ISLocalToGlobalMapping l2g = NULL;
7568: PetscLayout nmap = NULL;
7570: PetscLayoutDuplicate(mat->rmap, &nmap);
7571: if (mat->rmap->mapping) ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g);
7572: PetscLayoutDestroy(&mat->rmap);
7573: mat->rmap = nmap;
7574: mat->rmap->mapping = l2g;
7575: }
7576: if (mat->cmap->refcnt) {
7577: ISLocalToGlobalMapping l2g = NULL;
7578: PetscLayout nmap = NULL;
7580: PetscLayoutDuplicate(mat->cmap, &nmap);
7581: if (mat->cmap->mapping) ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g);
7582: PetscLayoutDestroy(&mat->cmap);
7583: mat->cmap = nmap;
7584: mat->cmap->mapping = l2g;
7585: }
7586: PetscLayoutSetBlockSize(mat->rmap, rbs);
7587: PetscLayoutSetBlockSize(mat->cmap, cbs);
7588: return 0;
7589: }
7591: /*@
7592: MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7594: Logically Collective on mat
7596: Input Parameters:
7597: + mat - the matrix
7598: . fromRow - matrix from which to copy row block size
7599: - fromCol - matrix from which to copy column block size (can be same as fromRow)
7601: Level: developer
7603: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7604: @*/
7605: PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7606: {
7610: if (fromRow->rmap->bs > 0) PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs);
7611: if (fromCol->cmap->bs > 0) PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs);
7612: return 0;
7613: }
7615: /*@
7616: MatResidual - Default routine to calculate the residual r = b - Ax
7618: Collective on mat
7620: Input Parameters:
7621: + mat - the matrix
7622: . b - the right-hand-side
7623: - x - the approximate solution
7625: Output Parameter:
7626: . r - location to store the residual
7628: Level: developer
7630: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7631: @*/
7632: PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7633: {
7639: MatCheckPreallocated(mat, 1);
7640: PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0);
7641: if (!mat->ops->residual) {
7642: MatMult(mat, x, r);
7643: VecAYPX(r, -1.0, b);
7644: } else {
7645: PetscUseTypeMethod(mat, residual, b, x, r);
7646: }
7647: PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0);
7648: return 0;
7649: }
7651: /*@C
7652: MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7654: Collective on mat
7656: Input Parameters:
7657: + mat - the matrix
7658: . shift - 0 or 1 indicating we want the indices starting at 0 or 1
7659: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7660: - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the
7661: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7662: always used.
7664: Output Parameters:
7665: + n - number of local rows in the (possibly compressed) matrix, use NULL if not needed
7666: . 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
7667: . ja - the column indices, use NULL if not needed
7668: - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7669: are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7671: Level: developer
7673: Notes:
7674: You CANNOT change any of the ia[] or ja[] values.
7676: Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7678: Fortran Notes:
7679: In Fortran use
7680: $
7681: $ PetscInt ia(1), ja(1)
7682: $ PetscOffset iia, jja
7683: $ call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7684: $ ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7686: or
7687: $
7688: $ PetscInt, pointer :: ia(:),ja(:)
7689: $ call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7690: $ ! Access the ith and jth entries via ia(i) and ja(j)
7692: .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7693: @*/
7694: PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7695: {
7702: MatCheckPreallocated(mat, 1);
7703: if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7704: else {
7705: if (done) *done = PETSC_TRUE;
7706: PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0);
7707: PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7708: PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0);
7709: }
7710: return 0;
7711: }
7713: /*@C
7714: MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7716: Collective on mat
7718: Input Parameters:
7719: + mat - the matrix
7720: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7721: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7722: symmetrized
7723: . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7724: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7725: always used.
7726: . n - number of columns in the (possibly compressed) matrix
7727: . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7728: - ja - the row indices
7730: Output Parameters:
7731: . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7733: Level: developer
7735: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7736: @*/
7737: PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7738: {
7745: MatCheckPreallocated(mat, 1);
7746: if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7747: else {
7748: *done = PETSC_TRUE;
7749: PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7750: }
7751: return 0;
7752: }
7754: /*@C
7755: MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7757: Collective on mat
7759: Input Parameters:
7760: + mat - the matrix
7761: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7762: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7763: . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7764: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7765: always used.
7766: . n - size of (possibly compressed) matrix
7767: . ia - the row pointers
7768: - ja - the column indices
7770: Output Parameters:
7771: . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7773: Note:
7774: This routine zeros out n, ia, and ja. This is to prevent accidental
7775: us of the array after it has been restored. If you pass NULL, it will
7776: not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7778: Level: developer
7780: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7781: @*/
7782: PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7783: {
7789: MatCheckPreallocated(mat, 1);
7791: if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7792: else {
7793: if (done) *done = PETSC_TRUE;
7794: PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7795: if (n) *n = 0;
7796: if (ia) *ia = NULL;
7797: if (ja) *ja = NULL;
7798: }
7799: return 0;
7800: }
7802: /*@C
7803: MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
7805: Collective on Mat
7807: Input Parameters:
7808: + mat - the matrix
7809: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7810: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7811: - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7812: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7813: always used.
7815: Output Parameters:
7816: + n - size of (possibly compressed) matrix
7817: . ia - the column pointers
7818: . ja - the row indices
7819: - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7821: Level: developer
7823: .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7824: @*/
7825: PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7826: {
7832: MatCheckPreallocated(mat, 1);
7834: if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7835: else {
7836: *done = PETSC_TRUE;
7837: PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7838: if (n) *n = 0;
7839: if (ia) *ia = NULL;
7840: if (ja) *ja = NULL;
7841: }
7842: return 0;
7843: }
7845: /*@C
7846: MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
7848: Collective on mat
7850: Input Parameters:
7851: + mat - the matrix
7852: . ncolors - max color value
7853: . n - number of entries in colorarray
7854: - colorarray - array indicating color for each column
7856: Output Parameters:
7857: . iscoloring - coloring generated using colorarray information
7859: Level: developer
7861: .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7862: @*/
7863: PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
7864: {
7869: MatCheckPreallocated(mat, 1);
7871: if (!mat->ops->coloringpatch) {
7872: ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring);
7873: } else {
7874: PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7875: }
7876: return 0;
7877: }
7879: /*@
7880: MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
7882: Logically Collective on mat
7884: Input Parameter:
7885: . mat - the factored matrix to be reset
7887: Notes:
7888: This routine should be used only with factored matrices formed by in-place
7889: factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
7890: format). This option can save memory, for example, when solving nonlinear
7891: systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7892: ILU(0) preconditioner.
7894: Note that one can specify in-place ILU(0) factorization by calling
7895: .vb
7896: PCType(pc,PCILU);
7897: PCFactorSeUseInPlace(pc);
7898: .ve
7899: or by using the options -pc_type ilu -pc_factor_in_place
7901: In-place factorization ILU(0) can also be used as a local
7902: solver for the blocks within the block Jacobi or additive Schwarz
7903: methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc
7904: for details on setting local solver options.
7906: Most users should employ the `KSP` interface for linear solvers
7907: instead of working directly with matrix algebra routines such as this.
7908: See, e.g., `KSPCreate()`.
7910: Level: developer
7912: .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7913: @*/
7914: PetscErrorCode MatSetUnfactored(Mat mat)
7915: {
7918: MatCheckPreallocated(mat, 1);
7919: mat->factortype = MAT_FACTOR_NONE;
7920: if (!mat->ops->setunfactored) return 0;
7921: PetscUseTypeMethod(mat, setunfactored);
7922: return 0;
7923: }
7925: /*MC
7926: MatDenseGetArrayF90 - Accesses a matrix array from Fortran
7928: Synopsis:
7929: MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7931: Not collective
7933: Input Parameter:
7934: . x - matrix
7936: Output Parameters:
7937: + xx_v - the Fortran pointer to the array
7938: - ierr - error code
7940: Example of Usage:
7941: .vb
7942: PetscScalar, pointer xx_v(:,:)
7943: ....
7944: call MatDenseGetArrayF90(x,xx_v,ierr)
7945: a = xx_v(3)
7946: call MatDenseRestoreArrayF90(x,xx_v,ierr)
7947: .ve
7949: Level: advanced
7951: .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
7953: M*/
7955: /*MC
7956: MatDenseRestoreArrayF90 - Restores a matrix array that has been
7957: accessed with `MatDenseGetArrayF90()`.
7959: Synopsis:
7960: MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7962: Not collective
7964: Input Parameters:
7965: + x - matrix
7966: - xx_v - the Fortran90 pointer to the array
7968: Output Parameter:
7969: . ierr - error code
7971: Example of Usage:
7972: .vb
7973: PetscScalar, pointer xx_v(:,:)
7974: ....
7975: call MatDenseGetArrayF90(x,xx_v,ierr)
7976: a = xx_v(3)
7977: call MatDenseRestoreArrayF90(x,xx_v,ierr)
7978: .ve
7980: Level: advanced
7982: .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
7984: M*/
7986: /*MC
7987: MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
7989: Synopsis:
7990: MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7992: Not collective
7994: Input Parameter:
7995: . x - matrix
7997: Output Parameters:
7998: + xx_v - the Fortran pointer to the array
7999: - ierr - error code
8001: Example of Usage:
8002: .vb
8003: PetscScalar, pointer xx_v(:)
8004: ....
8005: call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8006: a = xx_v(3)
8007: call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8008: .ve
8010: Level: advanced
8012: .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8014: M*/
8016: /*MC
8017: MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8018: accessed with `MatSeqAIJGetArrayF90()`.
8020: Synopsis:
8021: MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8023: Not collective
8025: Input Parameters:
8026: + x - matrix
8027: - xx_v - the Fortran90 pointer to the array
8029: Output Parameter:
8030: . ierr - error code
8032: Example of Usage:
8033: .vb
8034: PetscScalar, pointer xx_v(:)
8035: ....
8036: call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8037: a = xx_v(3)
8038: call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8039: .ve
8041: Level: advanced
8043: .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8045: M*/
8047: /*@
8048: MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8049: as the original matrix.
8051: Collective on mat
8053: Input Parameters:
8054: + mat - the original matrix
8055: . isrow - parallel IS containing the rows this processor should obtain
8056: . 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.
8057: - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8059: Output Parameter:
8060: . newmat - the new submatrix, of the same type as the old
8062: Level: advanced
8064: Notes:
8065: The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8067: Some matrix types place restrictions on the row and column indices, such
8068: 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;
8069: for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8071: The index sets may not have duplicate entries.
8073: The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8074: the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8075: to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8076: will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when
8077: you are finished using it.
8079: The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8080: the input matrix.
8082: If iscol is NULL then all columns are obtained (not supported in Fortran).
8084: Example usage:
8085: Consider the following 8x8 matrix with 34 non-zero values, that is
8086: assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8087: proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8088: as follows:
8090: .vb
8091: 1 2 0 | 0 3 0 | 0 4
8092: Proc0 0 5 6 | 7 0 0 | 8 0
8093: 9 0 10 | 11 0 0 | 12 0
8094: -------------------------------------
8095: 13 0 14 | 15 16 17 | 0 0
8096: Proc1 0 18 0 | 19 20 21 | 0 0
8097: 0 0 0 | 22 23 0 | 24 0
8098: -------------------------------------
8099: Proc2 25 26 27 | 0 0 28 | 29 0
8100: 30 0 0 | 31 32 33 | 0 34
8101: .ve
8103: Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is
8105: .vb
8106: 2 0 | 0 3 0 | 0
8107: Proc0 5 6 | 7 0 0 | 8
8108: -------------------------------
8109: Proc1 18 0 | 19 20 21 | 0
8110: -------------------------------
8111: Proc2 26 27 | 0 0 28 | 29
8112: 0 0 | 31 32 33 | 0
8113: .ve
8115: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8116: @*/
8117: PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8118: {
8119: PetscMPIInt size;
8120: Mat *local;
8121: IS iscoltmp;
8122: PetscBool flg;
8133: MatCheckPreallocated(mat, 1);
8134: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8136: if (!iscol || isrow == iscol) {
8137: PetscBool stride;
8138: PetscMPIInt grabentirematrix = 0, grab;
8139: PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride);
8140: if (stride) {
8141: PetscInt first, step, n, rstart, rend;
8142: ISStrideGetInfo(isrow, &first, &step);
8143: if (step == 1) {
8144: MatGetOwnershipRange(mat, &rstart, &rend);
8145: if (rstart == first) {
8146: ISGetLocalSize(isrow, &n);
8147: if (n == rend - rstart) grabentirematrix = 1;
8148: }
8149: }
8150: }
8151: MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat));
8152: if (grab) {
8153: PetscInfo(mat, "Getting entire matrix as submatrix\n");
8154: if (cll == MAT_INITIAL_MATRIX) {
8155: *newmat = mat;
8156: PetscObjectReference((PetscObject)mat);
8157: }
8158: return 0;
8159: }
8160: }
8162: if (!iscol) {
8163: ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp);
8164: } else {
8165: iscoltmp = iscol;
8166: }
8168: /* if original matrix is on just one processor then use submatrix generated */
8169: if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8170: MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat);
8171: goto setproperties;
8172: } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8173: MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local);
8174: *newmat = *local;
8175: PetscFree(local);
8176: goto setproperties;
8177: } else if (!mat->ops->createsubmatrix) {
8178: /* Create a new matrix type that implements the operation using the full matrix */
8179: PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8180: switch (cll) {
8181: case MAT_INITIAL_MATRIX:
8182: MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat);
8183: break;
8184: case MAT_REUSE_MATRIX:
8185: MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp);
8186: break;
8187: default:
8188: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8189: }
8190: PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8191: goto setproperties;
8192: }
8194: PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8195: PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8196: PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8198: setproperties:
8199: ISEqualUnsorted(isrow, iscoltmp, &flg);
8200: if (flg) MatPropagateSymmetryOptions(mat, *newmat);
8201: if (!iscol) ISDestroy(&iscoltmp);
8202: if (*newmat && cll == MAT_INITIAL_MATRIX) PetscObjectStateIncrease((PetscObject)*newmat);
8203: return 0;
8204: }
8206: /*@
8207: MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8209: Not Collective
8211: Input Parameters:
8212: + A - the matrix we wish to propagate options from
8213: - B - the matrix we wish to propagate options to
8215: Level: beginner
8217: Note:
8218: Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8220: .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8221: @*/
8222: PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8223: {
8226: B->symmetry_eternal = A->symmetry_eternal;
8227: B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8228: B->symmetric = A->symmetric;
8229: B->structurally_symmetric = A->structurally_symmetric;
8230: B->spd = A->spd;
8231: B->hermitian = A->hermitian;
8232: return 0;
8233: }
8235: /*@
8236: MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8237: used during the assembly process to store values that belong to
8238: other processors.
8240: Not Collective
8242: Input Parameters:
8243: + mat - the matrix
8244: . size - the initial size of the stash.
8245: - bsize - the initial size of the block-stash(if used).
8247: Options Database Keys:
8248: + -matstash_initial_size <size> or <size0,size1,...sizep-1>
8249: - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1>
8251: Level: intermediate
8253: Notes:
8254: The block-stash is used for values set with `MatSetValuesBlocked()` while
8255: the stash is used for values set with `MatSetValues()`
8257: Run with the option -info and look for output of the form
8258: MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8259: to determine the appropriate value, MM, to use for size and
8260: MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8261: to determine the value, BMM to use for bsize
8263: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8264: @*/
8265: PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8266: {
8269: MatStashSetInitialSize_Private(&mat->stash, size);
8270: MatStashSetInitialSize_Private(&mat->bstash, bsize);
8271: return 0;
8272: }
8274: /*@
8275: MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8276: the matrix
8278: Neighbor-wise Collective on mat
8280: Input Parameters:
8281: + mat - the matrix
8282: . x,y - the vectors
8283: - w - where the result is stored
8285: Level: intermediate
8287: Notes:
8288: w may be the same vector as y.
8290: This allows one to use either the restriction or interpolation (its transpose)
8291: matrix to do the interpolation
8293: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8294: @*/
8295: PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8296: {
8297: PetscInt M, N, Ny;
8303: MatGetSize(A, &M, &N);
8304: VecGetSize(y, &Ny);
8305: if (M == Ny) {
8306: MatMultAdd(A, x, y, w);
8307: } else {
8308: MatMultTransposeAdd(A, x, y, w);
8309: }
8310: return 0;
8311: }
8313: /*@
8314: MatInterpolate - y = A*x or A'*x depending on the shape of
8315: the matrix
8317: Neighbor-wise Collective on mat
8319: Input Parameters:
8320: + mat - the matrix
8321: - x,y - the vectors
8323: Level: intermediate
8325: Note:
8326: This allows one to use either the restriction or interpolation (its transpose)
8327: matrix to do the interpolation
8329: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8330: @*/
8331: PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8332: {
8333: PetscInt M, N, Ny;
8338: MatGetSize(A, &M, &N);
8339: VecGetSize(y, &Ny);
8340: if (M == Ny) {
8341: MatMult(A, x, y);
8342: } else {
8343: MatMultTranspose(A, x, y);
8344: }
8345: return 0;
8346: }
8348: /*@
8349: MatRestrict - y = A*x or A'*x
8351: Neighbor-wise Collective on Mat
8353: Input Parameters:
8354: + mat - the matrix
8355: - x,y - the vectors
8357: Level: intermediate
8359: Note:
8360: This allows one to use either the restriction or interpolation (its transpose)
8361: matrix to do the restriction
8363: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8364: @*/
8365: PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8366: {
8367: PetscInt M, N, Ny;
8372: MatGetSize(A, &M, &N);
8373: VecGetSize(y, &Ny);
8374: if (M == Ny) {
8375: MatMult(A, x, y);
8376: } else {
8377: MatMultTranspose(A, x, y);
8378: }
8379: return 0;
8380: }
8382: /*@
8383: MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8385: Neighbor-wise Collective on Mat
8387: Input Parameters:
8388: + mat - the matrix
8389: - w, x - the input dense matrices
8391: Output Parameters:
8392: . y - the output dense matrix
8394: Level: intermediate
8396: Note:
8397: This allows one to use either the restriction or interpolation (its transpose)
8398: matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8399: otherwise it will be recreated. y must be initialized to NULL if not supplied.
8401: .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8402: @*/
8403: PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8404: {
8405: PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8406: PetscBool trans = PETSC_TRUE;
8407: MatReuse reuse = MAT_INITIAL_MATRIX;
8414: MatGetSize(A, &M, &N);
8415: MatGetSize(x, &Mx, &Nx);
8416: if (N == Mx) trans = PETSC_FALSE;
8418: Mo = trans ? N : M;
8419: if (*y) {
8420: MatGetSize(*y, &My, &Ny);
8421: if (Mo == My && Nx == Ny) {
8422: reuse = MAT_REUSE_MATRIX;
8423: } else {
8425: MatDestroy(y);
8426: }
8427: }
8429: if (w && *y == w) { /* this is to minimize changes in PCMG */
8430: PetscBool flg;
8432: PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w);
8433: if (w) {
8434: PetscInt My, Ny, Mw, Nw;
8436: PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg);
8437: MatGetSize(*y, &My, &Ny);
8438: MatGetSize(w, &Mw, &Nw);
8439: if (!flg || My != Mw || Ny != Nw) w = NULL;
8440: }
8441: if (!w) {
8442: MatDuplicate(*y, MAT_COPY_VALUES, &w);
8443: PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w);
8444: PetscObjectDereference((PetscObject)w);
8445: } else {
8446: MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN);
8447: }
8448: }
8449: if (!trans) {
8450: MatMatMult(A, x, reuse, PETSC_DEFAULT, y);
8451: } else {
8452: MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y);
8453: }
8454: if (w) MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN);
8455: return 0;
8456: }
8458: /*@
8459: MatMatInterpolate - Y = A*X or A'*X
8461: Neighbor-wise Collective on Mat
8463: Input Parameters:
8464: + mat - the matrix
8465: - x - the input dense matrix
8467: Output Parameters:
8468: . y - the output dense matrix
8470: Level: intermediate
8472: Note:
8473: This allows one to use either the restriction or interpolation (its transpose)
8474: matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8475: otherwise it will be recreated. y must be initialized to NULL if not supplied.
8477: .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8478: @*/
8479: PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8480: {
8481: MatMatInterpolateAdd(A, x, NULL, y);
8482: return 0;
8483: }
8485: /*@
8486: MatMatRestrict - Y = A*X or A'*X
8488: Neighbor-wise Collective on Mat
8490: Input Parameters:
8491: + mat - the matrix
8492: - x - the input dense matrix
8494: Output Parameters:
8495: . y - the output dense matrix
8497: Level: intermediate
8499: Note:
8500: This allows one to use either the restriction or interpolation (its transpose)
8501: matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8502: otherwise it will be recreated. y must be initialized to NULL if not supplied.
8504: .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8505: @*/
8506: PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8507: {
8508: MatMatInterpolateAdd(A, x, NULL, y);
8509: return 0;
8510: }
8512: /*@
8513: MatGetNullSpace - retrieves the null space of a matrix.
8515: Logically Collective on mat
8517: Input Parameters:
8518: + mat - the matrix
8519: - nullsp - the null space object
8521: Level: developer
8523: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8524: @*/
8525: PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8526: {
8529: *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8530: return 0;
8531: }
8533: /*@
8534: MatSetNullSpace - attaches a null space to a matrix.
8536: Logically Collective on mat
8538: Input Parameters:
8539: + mat - the matrix
8540: - nullsp - the null space object
8542: Level: advanced
8544: Notes:
8545: This null space is used by the `KSP` linear solvers to solve singular systems.
8547: 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
8549: 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
8550: to zero but the linear system will still be solved in a least squares sense.
8552: The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8553: 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).
8554: 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
8555: 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
8556: 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).
8557: This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8559: If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8560: `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8561: routine also automatically calls `MatSetTransposeNullSpace()`.
8563: The user should call `MatNullSpaceDestroy()`.
8565: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8566: `KSPSetPCSide()`
8567: @*/
8568: PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8569: {
8572: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8573: MatNullSpaceDestroy(&mat->nullsp);
8574: mat->nullsp = nullsp;
8575: if (mat->symmetric == PETSC_BOOL3_TRUE) MatSetTransposeNullSpace(mat, nullsp);
8576: return 0;
8577: }
8579: /*@
8580: MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8582: Logically Collective on mat
8584: Input Parameters:
8585: + mat - the matrix
8586: - nullsp - the null space object
8588: Level: developer
8590: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8591: @*/
8592: PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8593: {
8597: *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8598: return 0;
8599: }
8601: /*@
8602: MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8604: Logically Collective on mat
8606: Input Parameters:
8607: + mat - the matrix
8608: - nullsp - the null space object
8610: Level: advanced
8612: Notes:
8613: This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8615: See `MatSetNullSpace()`
8617: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8618: @*/
8619: PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8620: {
8623: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8624: MatNullSpaceDestroy(&mat->transnullsp);
8625: mat->transnullsp = nullsp;
8626: return 0;
8627: }
8629: /*@
8630: MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8631: This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8633: Logically Collective on mat
8635: Input Parameters:
8636: + mat - the matrix
8637: - nullsp - the null space object
8639: Level: advanced
8641: Notes:
8642: Overwrites any previous near null space that may have been attached
8644: You can remove the null space by calling this routine with an nullsp of NULL
8646: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8647: @*/
8648: PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8649: {
8653: MatCheckPreallocated(mat, 1);
8654: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8655: MatNullSpaceDestroy(&mat->nearnullsp);
8656: mat->nearnullsp = nullsp;
8657: return 0;
8658: }
8660: /*@
8661: MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8663: Not Collective
8665: Input Parameter:
8666: . mat - the matrix
8668: Output Parameter:
8669: . nullsp - the null space object, NULL if not set
8671: Level: advanced
8673: .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8674: @*/
8675: PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8676: {
8680: MatCheckPreallocated(mat, 1);
8681: *nullsp = mat->nearnullsp;
8682: return 0;
8683: }
8685: /*@C
8686: MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8688: Collective on mat
8690: Input Parameters:
8691: + mat - the matrix
8692: . row - row/column permutation
8693: . fill - expected fill factor >= 1.0
8694: - level - level of fill, for ICC(k)
8696: Notes:
8697: Probably really in-place only when level of fill is zero, otherwise allocates
8698: new space to store factored matrix and deletes previous memory.
8700: Most users should employ the `KSP` interface for linear solvers
8701: instead of working directly with matrix algebra routines such as this.
8702: See, e.g., `KSPCreate()`.
8704: Level: developer
8706: Developer Note:
8707: The Fortran interface is not autogenerated as the f90
8708: interface definition cannot be generated correctly [due to `MatFactorInfo`]
8710: .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8711: @*/
8712: PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8713: {
8721: MatCheckPreallocated(mat, 1);
8722: PetscUseTypeMethod(mat, iccfactor, row, info);
8723: PetscObjectStateIncrease((PetscObject)mat);
8724: return 0;
8725: }
8727: /*@
8728: MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8729: ghosted ones.
8731: Not Collective
8733: Input Parameters:
8734: + mat - the matrix
8735: - diag - the diagonal values, including ghost ones
8737: Level: developer
8739: Notes:
8740: Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8742: This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8744: .seealso: `MatDiagonalScale()`
8745: @*/
8746: PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8747: {
8748: PetscMPIInt size;
8755: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
8756: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8757: if (size == 1) {
8758: PetscInt n, m;
8759: VecGetSize(diag, &n);
8760: MatGetSize(mat, NULL, &m);
8761: if (m == n) {
8762: MatDiagonalScale(mat, NULL, diag);
8763: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8764: } else {
8765: PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8766: }
8767: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
8768: PetscObjectStateIncrease((PetscObject)mat);
8769: return 0;
8770: }
8772: /*@
8773: MatGetInertia - Gets the inertia from a factored matrix
8775: Collective on mat
8777: Input Parameter:
8778: . mat - the matrix
8780: Output Parameters:
8781: + nneg - number of negative eigenvalues
8782: . nzero - number of zero eigenvalues
8783: - npos - number of positive eigenvalues
8785: Level: advanced
8787: Note:
8788: Matrix must have been factored by `MatCholeskyFactor()`
8790: .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8791: @*/
8792: PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8793: {
8798: PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8799: return 0;
8800: }
8802: /* ----------------------------------------------------------------*/
8803: /*@C
8804: MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8806: Neighbor-wise Collective on mat
8808: Input Parameters:
8809: + mat - the factored matrix obtained with `MatGetFactor()`
8810: - b - the right-hand-side vectors
8812: Output Parameter:
8813: . x - the result vectors
8815: Note:
8816: The vectors b and x cannot be the same. I.e., one cannot
8817: call `MatSolves`(A,x,x).
8819: Level: developer
8821: .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8822: @*/
8823: PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
8824: {
8829: if (!mat->rmap->N && !mat->cmap->N) return 0;
8831: MatCheckPreallocated(mat, 1);
8832: PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0);
8833: PetscUseTypeMethod(mat, solves, b, x);
8834: PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0);
8835: return 0;
8836: }
8838: /*@
8839: MatIsSymmetric - Test whether a matrix is symmetric
8841: Collective on mat
8843: Input Parameters:
8844: + A - the matrix to test
8845: - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
8847: Output Parameters:
8848: . flg - the result
8850: Notes:
8851: For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8853: If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
8855: One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8856: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8858: Level: intermediate
8860: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
8861: `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8862: @*/
8863: PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
8864: {
8868: if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8869: else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8870: else {
8871: if (!A->ops->issymmetric) {
8872: MatType mattype;
8873: MatGetType(A, &mattype);
8874: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8875: }
8876: PetscUseTypeMethod(A, issymmetric, tol, flg);
8877: if (!tol) MatSetOption(A, MAT_SYMMETRIC, *flg);
8878: }
8879: return 0;
8880: }
8882: /*@
8883: MatIsHermitian - Test whether a matrix is Hermitian
8885: Collective on Mat
8887: Input Parameters:
8888: + A - the matrix to test
8889: - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
8891: Output Parameters:
8892: . flg - the result
8894: Level: intermediate
8896: Notes:
8897: For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8899: If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
8901: One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8902: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
8904: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8905: `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8906: @*/
8907: PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
8908: {
8912: if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8913: else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8914: else {
8915: if (!A->ops->ishermitian) {
8916: MatType mattype;
8917: MatGetType(A, &mattype);
8918: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8919: }
8920: PetscUseTypeMethod(A, ishermitian, tol, flg);
8921: if (!tol) MatSetOption(A, MAT_HERMITIAN, *flg);
8922: }
8923: return 0;
8924: }
8926: /*@
8927: MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
8929: Not Collective
8931: Input Parameter:
8932: . A - the matrix to check
8934: Output Parameters:
8935: + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
8936: - flg - the result (only valid if set is `PETSC_TRUE`)
8938: Level: advanced
8940: Notes:
8941: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
8942: if you want it explicitly checked
8944: One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8945: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8947: .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8948: @*/
8949: PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
8950: {
8954: if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8955: *set = PETSC_TRUE;
8956: *flg = PetscBool3ToBool(A->symmetric);
8957: } else {
8958: *set = PETSC_FALSE;
8959: }
8960: return 0;
8961: }
8963: /*@
8964: MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
8966: Not Collective
8968: Input Parameter:
8969: . A - the matrix to check
8971: Output Parameters:
8972: + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
8973: - flg - the result (only valid if set is `PETSC_TRUE`)
8975: Level: advanced
8977: Notes:
8978: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
8980: One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
8981: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
8983: .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8984: @*/
8985: PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
8986: {
8990: if (A->spd != PETSC_BOOL3_UNKNOWN) {
8991: *set = PETSC_TRUE;
8992: *flg = PetscBool3ToBool(A->spd);
8993: } else {
8994: *set = PETSC_FALSE;
8995: }
8996: return 0;
8997: }
8999: /*@
9000: MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9002: Not Collective
9004: Input Parameter:
9005: . A - the matrix to check
9007: Output Parameters:
9008: + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9009: - flg - the result (only valid if set is `PETSC_TRUE`)
9011: Level: advanced
9013: Notes:
9014: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9015: if you want it explicitly checked
9017: One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9018: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9020: .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9021: @*/
9022: PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9023: {
9027: if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9028: *set = PETSC_TRUE;
9029: *flg = PetscBool3ToBool(A->hermitian);
9030: } else {
9031: *set = PETSC_FALSE;
9032: }
9033: return 0;
9034: }
9036: /*@
9037: MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9039: Collective on Mat
9041: Input Parameter:
9042: . A - the matrix to test
9044: Output Parameters:
9045: . flg - the result
9047: Notes:
9048: If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9050: 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
9051: symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9053: Level: intermediate
9055: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9056: @*/
9057: PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9058: {
9061: if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9062: *flg = PetscBool3ToBool(A->structurally_symmetric);
9063: } else {
9064: PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9065: MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg);
9066: }
9067: return 0;
9068: }
9070: /*@
9071: MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9073: Not Collective
9075: Input Parameter:
9076: . A - the matrix to check
9078: Output Parameters:
9079: + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9080: - flg - the result (only valid if set is PETSC_TRUE)
9082: Level: advanced
9084: Notes:
9085: 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
9086: symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9088: Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9090: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9091: @*/
9092: PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9093: {
9097: if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9098: *set = PETSC_TRUE;
9099: *flg = PetscBool3ToBool(A->structurally_symmetric);
9100: } else {
9101: *set = PETSC_FALSE;
9102: }
9103: return 0;
9104: }
9106: /*@
9107: MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9108: to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9110: Not collective
9112: Input Parameter:
9113: . mat - the matrix
9115: Output Parameters:
9116: + nstash - the size of the stash
9117: . reallocs - the number of additional mallocs incurred.
9118: . bnstash - the size of the block stash
9119: - breallocs - the number of additional mallocs incurred.in the block stash
9121: Level: advanced
9123: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9124: @*/
9125: PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9126: {
9127: MatStashGetInfo_Private(&mat->stash, nstash, reallocs);
9128: MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs);
9129: return 0;
9130: }
9132: /*@C
9133: MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9134: parallel layout, `PetscLayout` for rows and columns
9136: Collective on mat
9138: Input Parameter:
9139: . mat - the matrix
9141: Output Parameters:
9142: + right - (optional) vector that the matrix can be multiplied against
9143: - left - (optional) vector that the matrix vector product can be stored in
9145: Notes:
9146: 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()`.
9148: These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9150: Level: advanced
9152: .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9153: @*/
9154: PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9155: {
9158: if (mat->ops->getvecs) {
9159: PetscUseTypeMethod(mat, getvecs, right, left);
9160: } else {
9161: PetscInt rbs, cbs;
9162: MatGetBlockSizes(mat, &rbs, &cbs);
9163: if (right) {
9165: VecCreate(PetscObjectComm((PetscObject)mat), right);
9166: VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE);
9167: VecSetBlockSize(*right, cbs);
9168: VecSetType(*right, mat->defaultvectype);
9169: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9170: if (mat->boundtocpu && mat->bindingpropagates) {
9171: VecSetBindingPropagates(*right, PETSC_TRUE);
9172: VecBindToCPU(*right, PETSC_TRUE);
9173: }
9174: #endif
9175: PetscLayoutReference(mat->cmap, &(*right)->map);
9176: }
9177: if (left) {
9179: VecCreate(PetscObjectComm((PetscObject)mat), left);
9180: VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE);
9181: VecSetBlockSize(*left, rbs);
9182: VecSetType(*left, mat->defaultvectype);
9183: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9184: if (mat->boundtocpu && mat->bindingpropagates) {
9185: VecSetBindingPropagates(*left, PETSC_TRUE);
9186: VecBindToCPU(*left, PETSC_TRUE);
9187: }
9188: #endif
9189: PetscLayoutReference(mat->rmap, &(*left)->map);
9190: }
9191: }
9192: return 0;
9193: }
9195: /*@C
9196: MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9197: with default values.
9199: Not Collective
9201: Input Parameters:
9202: . info - the `MatFactorInfo` data structure
9204: Notes:
9205: The solvers are generally used through the `KSP` and `PC` objects, for example
9206: `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9208: Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9210: Level: developer
9212: Developer Note:
9213: The Fortran interface is not autogenerated as the f90
9214: interface definition cannot be generated correctly [due to `MatFactorInfo`]
9216: .seealso: `MatGetFactor()`, `MatFactorInfo`
9217: @*/
9218: PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9219: {
9220: PetscMemzero(info, sizeof(MatFactorInfo));
9221: return 0;
9222: }
9224: /*@
9225: MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9227: Collective on mat
9229: Input Parameters:
9230: + mat - the factored matrix
9231: - is - the index set defining the Schur indices (0-based)
9233: Notes:
9234: Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9236: You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9238: This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9240: Level: advanced
9242: .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9243: `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9245: @*/
9246: PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9247: {
9248: PetscErrorCode (*f)(Mat, IS);
9256: PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f);
9258: MatDestroy(&mat->schur);
9259: (*f)(mat, is);
9261: return 0;
9262: }
9264: /*@
9265: MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9267: Logically Collective on mat
9269: Input Parameters:
9270: + F - the factored matrix obtained by calling `MatGetFactor()`
9271: . S - location where to return the Schur complement, can be NULL
9272: - status - the status of the Schur complement matrix, can be NULL
9274: Notes:
9275: You must call `MatFactorSetSchurIS()` before calling this routine.
9277: This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9279: The routine provides a copy of the Schur matrix stored within the solver data structures.
9280: The caller must destroy the object when it is no longer needed.
9281: If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9283: 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)
9285: See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9287: Developer Note:
9288: The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9289: matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9291: Level: advanced
9293: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9294: @*/
9295: PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9296: {
9300: if (S) {
9301: PetscErrorCode (*f)(Mat, Mat *);
9303: PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f);
9304: if (f) {
9305: (*f)(F, S);
9306: } else {
9307: MatDuplicate(F->schur, MAT_COPY_VALUES, S);
9308: }
9309: }
9310: if (status) *status = F->schur_status;
9311: return 0;
9312: }
9314: /*@
9315: MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9317: Logically Collective on mat
9319: Input Parameters:
9320: + F - the factored matrix obtained by calling `MatGetFactor()`
9321: . *S - location where to return the Schur complement, can be NULL
9322: - status - the status of the Schur complement matrix, can be NULL
9324: Notes:
9325: You must call `MatFactorSetSchurIS()` before calling this routine.
9327: Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9329: The routine returns a the Schur Complement stored within the data strutures of the solver.
9331: If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9333: The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9335: Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9337: See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9339: Level: advanced
9341: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9342: @*/
9343: PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9344: {
9348: if (S) *S = F->schur;
9349: if (status) *status = F->schur_status;
9350: return 0;
9351: }
9353: /*@
9354: MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9356: Logically Collective on mat
9358: Input Parameters:
9359: + F - the factored matrix obtained by calling `MatGetFactor()`
9360: . *S - location where the Schur complement is stored
9361: - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9363: Level: advanced
9365: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9366: @*/
9367: PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9368: {
9370: if (S) {
9372: *S = NULL;
9373: }
9374: F->schur_status = status;
9375: MatFactorUpdateSchurStatus_Private(F);
9376: return 0;
9377: }
9379: /*@
9380: MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9382: Logically Collective on mat
9384: Input Parameters:
9385: + F - the factored matrix obtained by calling `MatGetFactor()`
9386: . rhs - location where the right hand side of the Schur complement system is stored
9387: - sol - location where the solution of the Schur complement system has to be returned
9389: Notes:
9390: The sizes of the vectors should match the size of the Schur complement
9392: Must be called after `MatFactorSetSchurIS()`
9394: Level: advanced
9396: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9397: @*/
9398: PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9399: {
9408: MatFactorFactorizeSchurComplement(F);
9409: switch (F->schur_status) {
9410: case MAT_FACTOR_SCHUR_FACTORED:
9411: MatSolveTranspose(F->schur, rhs, sol);
9412: break;
9413: case MAT_FACTOR_SCHUR_INVERTED:
9414: MatMultTranspose(F->schur, rhs, sol);
9415: break;
9416: default:
9417: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9418: }
9419: return 0;
9420: }
9422: /*@
9423: MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9425: Logically Collective on mat
9427: Input Parameters:
9428: + F - the factored matrix obtained by calling `MatGetFactor()`
9429: . rhs - location where the right hand side of the Schur complement system is stored
9430: - sol - location where the solution of the Schur complement system has to be returned
9432: Notes:
9433: The sizes of the vectors should match the size of the Schur complement
9435: Must be called after `MatFactorSetSchurIS()`
9437: Level: advanced
9439: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9440: @*/
9441: PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9442: {
9451: MatFactorFactorizeSchurComplement(F);
9452: switch (F->schur_status) {
9453: case MAT_FACTOR_SCHUR_FACTORED:
9454: MatSolve(F->schur, rhs, sol);
9455: break;
9456: case MAT_FACTOR_SCHUR_INVERTED:
9457: MatMult(F->schur, rhs, sol);
9458: break;
9459: default:
9460: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9461: }
9462: return 0;
9463: }
9465: /*@
9466: MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9468: Logically Collective on F
9470: Input Parameters:
9471: . F - the factored matrix obtained by calling `MatGetFactor()`
9473: Notes:
9474: Must be called after `MatFactorSetSchurIS()`.
9476: Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9478: Level: advanced
9480: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9481: @*/
9482: PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9483: {
9486: if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) return 0;
9487: MatFactorFactorizeSchurComplement(F);
9488: MatFactorInvertSchurComplement_Private(F);
9489: F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9490: return 0;
9491: }
9493: /*@
9494: MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9496: Logically Collective on mat
9498: Input Parameters:
9499: . F - the factored matrix obtained by calling `MatGetFactor()`
9501: Note:
9502: Must be called after `MatFactorSetSchurIS()`
9504: Level: advanced
9506: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9507: @*/
9508: PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9509: {
9512: if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) return 0;
9513: MatFactorFactorizeSchurComplement_Private(F);
9514: F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9515: return 0;
9516: }
9518: /*@
9519: MatPtAP - Creates the matrix product C = P^T * A * P
9521: Neighbor-wise Collective on A
9523: Input Parameters:
9524: + A - the matrix
9525: . P - the projection matrix
9526: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9527: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9528: if the result is a dense matrix this is irrelevant
9530: Output Parameters:
9531: . C - the product matrix
9533: Notes:
9534: C will be created and must be destroyed by the user with `MatDestroy()`.
9536: An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9538: Developer Note:
9539: For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9541: Level: intermediate
9543: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9544: @*/
9545: PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9546: {
9547: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9550: if (scall == MAT_INITIAL_MATRIX) {
9551: MatProductCreate(A, P, NULL, C);
9552: MatProductSetType(*C, MATPRODUCT_PtAP);
9553: MatProductSetAlgorithm(*C, "default");
9554: MatProductSetFill(*C, fill);
9556: (*C)->product->api_user = PETSC_TRUE;
9557: MatProductSetFromOptions(*C);
9559: MatProductSymbolic(*C);
9560: } else { /* scall == MAT_REUSE_MATRIX */
9561: MatProductReplaceMats(A, P, NULL, *C);
9562: }
9564: MatProductNumeric(*C);
9565: (*C)->symmetric = A->symmetric;
9566: (*C)->spd = A->spd;
9567: return 0;
9568: }
9570: /*@
9571: MatRARt - Creates the matrix product C = R * A * R^T
9573: Neighbor-wise Collective on A
9575: Input Parameters:
9576: + A - the matrix
9577: . R - the projection matrix
9578: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9579: - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9580: if the result is a dense matrix this is irrelevant
9582: Output Parameters:
9583: . C - the product matrix
9585: Notes:
9586: C will be created and must be destroyed by the user with `MatDestroy()`.
9588: An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9590: This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9591: which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9592: parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9593: We recommend using MatPtAP().
9595: Level: intermediate
9597: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9598: @*/
9599: PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9600: {
9601: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9604: if (scall == MAT_INITIAL_MATRIX) {
9605: MatProductCreate(A, R, NULL, C);
9606: MatProductSetType(*C, MATPRODUCT_RARt);
9607: MatProductSetAlgorithm(*C, "default");
9608: MatProductSetFill(*C, fill);
9610: (*C)->product->api_user = PETSC_TRUE;
9611: MatProductSetFromOptions(*C);
9613: MatProductSymbolic(*C);
9614: } else { /* scall == MAT_REUSE_MATRIX */
9615: MatProductReplaceMats(A, R, NULL, *C);
9616: }
9618: MatProductNumeric(*C);
9619: if (A->symmetric == PETSC_BOOL3_TRUE) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9620: return 0;
9621: }
9623: static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9624: {
9627: if (scall == MAT_INITIAL_MATRIX) {
9628: PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]);
9629: MatProductCreate(A, B, NULL, C);
9630: MatProductSetType(*C, ptype);
9631: MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT);
9632: MatProductSetFill(*C, fill);
9634: (*C)->product->api_user = PETSC_TRUE;
9635: MatProductSetFromOptions(*C);
9636: MatProductSymbolic(*C);
9637: } else { /* scall == MAT_REUSE_MATRIX */
9638: Mat_Product *product = (*C)->product;
9639: PetscBool isdense;
9641: PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "");
9642: if (isdense && product && product->type != ptype) {
9643: MatProductClear(*C);
9644: product = NULL;
9645: }
9646: PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]);
9647: if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9648: if (isdense) {
9649: MatProductCreate_Private(A, B, NULL, *C);
9650: product = (*C)->product;
9651: product->fill = fill;
9652: product->api_user = PETSC_TRUE;
9653: product->clear = PETSC_TRUE;
9655: MatProductSetType(*C, ptype);
9656: MatProductSetFromOptions(*C);
9658: MatProductSymbolic(*C);
9659: } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9660: } else { /* user may change input matrices A or B when REUSE */
9661: MatProductReplaceMats(A, B, NULL, *C);
9662: }
9663: }
9664: MatProductNumeric(*C);
9665: return 0;
9666: }
9668: /*@
9669: MatMatMult - Performs matrix-matrix multiplication C=A*B.
9671: Neighbor-wise Collective on A
9673: Input Parameters:
9674: + A - the left matrix
9675: . B - the right matrix
9676: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9677: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9678: if the result is a dense matrix this is irrelevant
9680: Output Parameters:
9681: . C - the product matrix
9683: Notes:
9684: Unless scall is `MAT_REUSE_MATRIX` C will be created.
9686: `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
9687: call to this function with `MAT_INITIAL_MATRIX`.
9689: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9691: 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`,
9692: rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9694: Example of Usage:
9695: .vb
9696: MatProductCreate(A,B,NULL,&C);
9697: MatProductSetType(C,MATPRODUCT_AB);
9698: MatProductSymbolic(C);
9699: MatProductNumeric(C); // compute C=A * B
9700: MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9701: MatProductNumeric(C);
9702: MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9703: MatProductNumeric(C);
9704: .ve
9706: Level: intermediate
9708: .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9709: @*/
9710: PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9711: {
9712: MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C);
9713: return 0;
9714: }
9716: /*@
9717: MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9719: Neighbor-wise Collective on A
9721: Input Parameters:
9722: + A - the left matrix
9723: . B - the right matrix
9724: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9725: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9727: Output Parameters:
9728: . C - the product matrix
9730: Notes:
9731: C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9733: `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9735: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9736: actually needed.
9738: This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9739: and for pairs of `MATMPIDENSE` matrices.
9741: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
9743: Options Database Keys:
9744: . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9745: first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9746: the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9748: Level: intermediate
9750: .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9751: @*/
9752: PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9753: {
9754: MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C);
9755: if (A == B) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9756: return 0;
9757: }
9759: /*@
9760: MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
9762: Neighbor-wise Collective on A
9764: Input Parameters:
9765: + A - the left matrix
9766: . B - the right matrix
9767: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9768: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9770: Output Parameters:
9771: . C - the product matrix
9773: Notes:
9774: C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9776: `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9778: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
9780: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9781: actually needed.
9783: This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9784: which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices.
9786: Level: intermediate
9788: .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9789: @*/
9790: PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9791: {
9792: MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C);
9793: return 0;
9794: }
9796: /*@
9797: MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
9799: Neighbor-wise Collective on A
9801: Input Parameters:
9802: + A - the left matrix
9803: . B - the middle matrix
9804: . C - the right matrix
9805: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9806: - 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
9807: if the result is a dense matrix this is irrelevant
9809: Output Parameters:
9810: . D - the product matrix
9812: Notes:
9813: Unless scall is `MAT_REUSE_MATRIX` D will be created.
9815: `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9817: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
9819: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9820: actually needed.
9822: If you have many matrices with the same non-zero structure to multiply, you
9823: should use `MAT_REUSE_MATRIX` in all calls but the first
9825: Level: intermediate
9827: .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9828: @*/
9829: PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
9830: {
9831: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
9834: if (scall == MAT_INITIAL_MATRIX) {
9835: MatProductCreate(A, B, C, D);
9836: MatProductSetType(*D, MATPRODUCT_ABC);
9837: MatProductSetAlgorithm(*D, "default");
9838: MatProductSetFill(*D, fill);
9840: (*D)->product->api_user = PETSC_TRUE;
9841: MatProductSetFromOptions(*D);
9843: ((PetscObject)C)->type_name);
9844: MatProductSymbolic(*D);
9845: } else { /* user may change input matrices when REUSE */
9846: MatProductReplaceMats(A, B, C, *D);
9847: }
9848: MatProductNumeric(*D);
9849: return 0;
9850: }
9852: /*@
9853: MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9855: Collective on mat
9857: Input Parameters:
9858: + mat - the matrix
9859: . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9860: . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
9861: - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9863: Output Parameter:
9864: . matredundant - redundant matrix
9866: Notes:
9867: `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
9868: original matrix has not changed from that last call to MatCreateRedundantMatrix().
9870: This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9871: calling it.
9873: `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
9875: Level: advanced
9877: .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
9878: @*/
9879: PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
9880: {
9881: MPI_Comm comm;
9882: PetscMPIInt size;
9883: PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9884: Mat_Redundant *redund = NULL;
9885: PetscSubcomm psubcomm = NULL;
9886: MPI_Comm subcomm_in = subcomm;
9887: Mat *matseq;
9888: IS isrow, iscol;
9889: PetscBool newsubcomm = PETSC_FALSE;
9892: if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9895: }
9897: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
9898: if (size == 1 || nsubcomm == 1) {
9899: if (reuse == MAT_INITIAL_MATRIX) {
9900: MatDuplicate(mat, MAT_COPY_VALUES, matredundant);
9901: } else {
9903: MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN);
9904: }
9905: return 0;
9906: }
9910: MatCheckPreallocated(mat, 1);
9912: PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0);
9913: if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9914: /* create psubcomm, then get subcomm */
9915: PetscObjectGetComm((PetscObject)mat, &comm);
9916: MPI_Comm_size(comm, &size);
9919: PetscSubcommCreate(comm, &psubcomm);
9920: PetscSubcommSetNumber(psubcomm, nsubcomm);
9921: PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS);
9922: PetscSubcommSetFromOptions(psubcomm);
9923: PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL);
9924: newsubcomm = PETSC_TRUE;
9925: PetscSubcommDestroy(&psubcomm);
9926: }
9928: /* get isrow, iscol and a local sequential matrix matseq[0] */
9929: if (reuse == MAT_INITIAL_MATRIX) {
9930: mloc_sub = PETSC_DECIDE;
9931: nloc_sub = PETSC_DECIDE;
9932: if (bs < 1) {
9933: PetscSplitOwnership(subcomm, &mloc_sub, &M);
9934: PetscSplitOwnership(subcomm, &nloc_sub, &N);
9935: } else {
9936: PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M);
9937: PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N);
9938: }
9939: MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm);
9940: rstart = rend - mloc_sub;
9941: ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow);
9942: ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol);
9943: } else { /* reuse == MAT_REUSE_MATRIX */
9945: /* retrieve subcomm */
9946: PetscObjectGetComm((PetscObject)(*matredundant), &subcomm);
9947: redund = (*matredundant)->redundant;
9948: isrow = redund->isrow;
9949: iscol = redund->iscol;
9950: matseq = redund->matseq;
9951: }
9952: MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq);
9954: /* get matredundant over subcomm */
9955: if (reuse == MAT_INITIAL_MATRIX) {
9956: MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant);
9958: /* create a supporting struct and attach it to C for reuse */
9959: PetscNew(&redund);
9960: (*matredundant)->redundant = redund;
9961: redund->isrow = isrow;
9962: redund->iscol = iscol;
9963: redund->matseq = matseq;
9964: if (newsubcomm) {
9965: redund->subcomm = subcomm;
9966: } else {
9967: redund->subcomm = MPI_COMM_NULL;
9968: }
9969: } else {
9970: MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant);
9971: }
9972: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9973: if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
9974: MatBindToCPU(*matredundant, PETSC_TRUE);
9975: MatSetBindingPropagates(*matredundant, PETSC_TRUE);
9976: }
9977: #endif
9978: PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0);
9979: return 0;
9980: }
9982: /*@C
9983: MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
9984: a given `Mat`. Each submatrix can span multiple procs.
9986: Collective on mat
9988: Input Parameters:
9989: + mat - the matrix
9990: . subcomm - the subcommunicator obtained by MPI_Com_split(comm)
9991: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9993: Output Parameter:
9994: . subMat - 'parallel submatrices each spans a given subcomm
9996: Notes:
9997: The submatrix partition across processors is dictated by 'subComm' a
9998: communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
9999: is not restriced to be grouped with consecutive original ranks.
10001: Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10002: map directly to the layout of the original matrix [wrt the local
10003: row,col partitioning]. So the original 'DiagonalMat' naturally maps
10004: into the 'DiagonalMat' of the subMat, hence it is used directly from
10005: the subMat. However the offDiagMat looses some columns - and this is
10006: reconstructed with `MatSetValues()`
10008: This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10010: Level: advanced
10012: .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10013: @*/
10014: PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10015: {
10016: PetscMPIInt commsize, subCommSize;
10018: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize);
10019: MPI_Comm_size(subComm, &subCommSize);
10023: PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10024: PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10025: PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10026: return 0;
10027: }
10029: /*@
10030: MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10032: Not Collective
10034: Input Parameters:
10035: + mat - matrix to extract local submatrix from
10036: . isrow - local row indices for submatrix
10037: - iscol - local column indices for submatrix
10039: Output Parameter:
10040: . submat - the submatrix
10042: Level: intermediate
10044: Notes:
10045: The submat should be returned with `MatRestoreLocalSubMatrix()`.
10047: Depending on the format of mat, the returned submat may not implement `MatMult()`. Its communicator may be
10048: the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.
10050: The submat always implements `MatSetValuesLocal()`. If isrow and iscol have the same block size, then
10051: `MatSetValuesBlockedLocal()` will also be implemented.
10053: The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10054: Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10056: .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10057: @*/
10058: PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10059: {
10067: if (mat->ops->getlocalsubmatrix) {
10068: PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10069: } else {
10070: MatCreateLocalRef(mat, isrow, iscol, submat);
10071: }
10072: return 0;
10073: }
10075: /*@
10076: MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10078: Not Collective
10080: Input Parameters:
10081: + mat - matrix to extract local submatrix from
10082: . isrow - local row indices for submatrix
10083: . iscol - local column indices for submatrix
10084: - submat - the submatrix
10086: Level: intermediate
10088: .seealso: `MatGetLocalSubMatrix()`
10089: @*/
10090: PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10091: {
10099: if (mat->ops->restorelocalsubmatrix) {
10100: PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10101: } else {
10102: MatDestroy(submat);
10103: }
10104: *submat = NULL;
10105: return 0;
10106: }
10108: /* --------------------------------------------------------*/
10109: /*@
10110: MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10112: Collective on mat
10114: Input Parameter:
10115: . mat - the matrix
10117: Output Parameter:
10118: . is - if any rows have zero diagonals this contains the list of them
10120: Level: developer
10122: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10123: @*/
10124: PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10125: {
10131: if (!mat->ops->findzerodiagonals) {
10132: Vec diag;
10133: const PetscScalar *a;
10134: PetscInt *rows;
10135: PetscInt rStart, rEnd, r, nrow = 0;
10137: MatCreateVecs(mat, &diag, NULL);
10138: MatGetDiagonal(mat, diag);
10139: MatGetOwnershipRange(mat, &rStart, &rEnd);
10140: VecGetArrayRead(diag, &a);
10141: for (r = 0; r < rEnd - rStart; ++r)
10142: if (a[r] == 0.0) ++nrow;
10143: PetscMalloc1(nrow, &rows);
10144: nrow = 0;
10145: for (r = 0; r < rEnd - rStart; ++r)
10146: if (a[r] == 0.0) rows[nrow++] = r + rStart;
10147: VecRestoreArrayRead(diag, &a);
10148: VecDestroy(&diag);
10149: ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is);
10150: } else {
10151: PetscUseTypeMethod(mat, findzerodiagonals, is);
10152: }
10153: return 0;
10154: }
10156: /*@
10157: MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10159: Collective on mat
10161: Input Parameter:
10162: . mat - the matrix
10164: Output Parameter:
10165: . is - contains the list of rows with off block diagonal entries
10167: Level: developer
10169: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10170: @*/
10171: PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10172: {
10178: PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10179: return 0;
10180: }
10182: /*@C
10183: MatInvertBlockDiagonal - Inverts the block diagonal entries.
10185: Collective on mat
10187: Input Parameters:
10188: . mat - the matrix
10190: Output Parameters:
10191: . values - the block inverses in column major order (FORTRAN-like)
10193: Notes:
10194: The size of the blocks is determined by the block size of the matrix.
10196: The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10198: The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10200: Fortran Note:
10201: This routine is not available from Fortran.
10203: Level: advanced
10205: .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10206: @*/
10207: PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10208: {
10212: PetscUseTypeMethod(mat, invertblockdiagonal, values);
10213: return 0;
10214: }
10216: /*@C
10217: MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10219: Collective on mat
10221: Input Parameters:
10222: + mat - the matrix
10223: . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10224: - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10226: Output Parameters:
10227: . values - the block inverses in column major order (FORTRAN-like)
10229: Notes:
10230: Use `MatInvertBlockDiagonal()` if all blocks have the same size
10232: The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10234: Fortran Note:
10235: This routine is not available from Fortran.
10237: Level: advanced
10239: .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10240: @*/
10241: PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10242: {
10246: PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10247: return 0;
10248: }
10250: /*@
10251: MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10253: Collective on Mat
10255: Input Parameters:
10256: + A - the matrix
10257: - C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set.
10259: Note:
10260: The blocksize of the matrix is used to determine the blocks on the diagonal of C
10262: Level: advanced
10264: .seealso: `MatInvertBlockDiagonal()`
10265: @*/
10266: PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10267: {
10268: const PetscScalar *vals;
10269: PetscInt *dnnz;
10270: PetscInt m, rstart, rend, bs, i, j;
10272: MatInvertBlockDiagonal(A, &vals);
10273: MatGetBlockSize(A, &bs);
10274: MatGetLocalSize(A, &m, NULL);
10275: MatSetLayouts(C, A->rmap, A->cmap);
10276: PetscMalloc1(m / bs, &dnnz);
10277: for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10278: MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL);
10279: PetscFree(dnnz);
10280: MatGetOwnershipRange(C, &rstart, &rend);
10281: MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE);
10282: for (i = rstart / bs; i < rend / bs; i++) MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES);
10283: MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY);
10284: MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY);
10285: MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE);
10286: return 0;
10287: }
10289: /*@C
10290: MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10291: via `MatTransposeColoringCreate()`.
10293: Collective on c
10295: Input Parameter:
10296: . c - coloring context
10298: Level: intermediate
10300: .seealso: `MatTransposeColoringCreate()`
10301: @*/
10302: PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10303: {
10304: MatTransposeColoring matcolor = *c;
10306: if (!matcolor) return 0;
10307: if (--((PetscObject)matcolor)->refct > 0) {
10308: matcolor = NULL;
10309: return 0;
10310: }
10312: PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow);
10313: PetscFree(matcolor->rows);
10314: PetscFree(matcolor->den2sp);
10315: PetscFree(matcolor->colorforcol);
10316: PetscFree(matcolor->columns);
10317: if (matcolor->brows > 0) PetscFree(matcolor->lstart);
10318: PetscHeaderDestroy(c);
10319: return 0;
10320: }
10322: /*@C
10323: MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10324: a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10325: `MatTransposeColoring` to sparse B.
10327: Collective on coloring
10329: Input Parameters:
10330: + B - sparse matrix B
10331: . Btdense - symbolic dense matrix B^T
10332: - coloring - coloring context created with `MatTransposeColoringCreate()`
10334: Output Parameter:
10335: . Btdense - dense matrix B^T
10337: Level: developer
10339: Note:
10340: These are used internally for some implementations of `MatRARt()`
10342: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10344: @*/
10345: PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10346: {
10351: (B->ops->transcoloringapplysptoden)(coloring, B, Btdense);
10352: return 0;
10353: }
10355: /*@C
10356: MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10357: a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10358: in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10359: Csp from Cden.
10361: Collective on matcoloring
10363: Input Parameters:
10364: + coloring - coloring context created with `MatTransposeColoringCreate()`
10365: - Cden - matrix product of a sparse matrix and a dense matrix Btdense
10367: Output Parameter:
10368: . Csp - sparse matrix
10370: Level: developer
10372: Note:
10373: These are used internally for some implementations of `MatRARt()`
10375: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10377: @*/
10378: PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10379: {
10384: (Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp);
10385: MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY);
10386: MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY);
10387: return 0;
10388: }
10390: /*@C
10391: MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10393: Collective on mat
10395: Input Parameters:
10396: + mat - the matrix product C
10397: - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10399: Output Parameter:
10400: . color - the new coloring context
10402: Level: intermediate
10404: .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10405: `MatTransColoringApplyDenToSp()`
10406: @*/
10407: PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10408: {
10409: MatTransposeColoring c;
10410: MPI_Comm comm;
10412: PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10413: PetscObjectGetComm((PetscObject)mat, &comm);
10414: PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL);
10416: c->ctype = iscoloring->ctype;
10417: if (mat->ops->transposecoloringcreate) {
10418: PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10419: } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10421: *color = c;
10422: PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10423: return 0;
10424: }
10426: /*@
10427: MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10428: matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10429: same, otherwise it will be larger
10431: Not Collective
10433: Input Parameter:
10434: . A - the matrix
10436: Output Parameter:
10437: . state - the current state
10439: Notes:
10440: You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10441: different matrices
10443: Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10445: Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10447: Level: intermediate
10449: .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10450: @*/
10451: PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10452: {
10454: *state = mat->nonzerostate;
10455: return 0;
10456: }
10458: /*@
10459: MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10460: matrices from each processor
10462: Collective
10464: Input Parameters:
10465: + comm - the communicators the parallel matrix will live on
10466: . seqmat - the input sequential matrices
10467: . n - number of local columns (or `PETSC_DECIDE`)
10468: - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10470: Output Parameter:
10471: . mpimat - the parallel matrix generated
10473: Level: developer
10475: Note:
10476: The number of columns of the matrix in EACH processor MUST be the same.
10478: .seealso: `Mat`
10479: @*/
10480: PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10481: {
10482: PetscMPIInt size;
10484: MPI_Comm_size(comm, &size);
10485: if (size == 1) {
10486: if (reuse == MAT_INITIAL_MATRIX) {
10487: MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat);
10488: } else {
10489: MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN);
10490: }
10491: return 0;
10492: }
10496: PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0);
10497: (*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat);
10498: PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0);
10499: return 0;
10500: }
10502: /*@
10503: MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10505: Collective on A
10507: Input Parameters:
10508: + A - the matrix to create subdomains from
10509: - N - requested number of subdomains
10511: Output Parameters:
10512: + n - number of subdomains resulting on this rank
10513: - iss - `IS` list with indices of subdomains on this rank
10515: Level: advanced
10517: Note:
10518: The number of subdomains must be smaller than the communicator size
10520: .seealso: `Mat`, `IS`
10521: @*/
10522: PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10523: {
10524: MPI_Comm comm, subcomm;
10525: PetscMPIInt size, rank, color;
10526: PetscInt rstart, rend, k;
10528: PetscObjectGetComm((PetscObject)A, &comm);
10529: MPI_Comm_size(comm, &size);
10530: MPI_Comm_rank(comm, &rank);
10532: *n = 1;
10533: k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10534: color = rank / k;
10535: MPI_Comm_split(comm, color, rank, &subcomm);
10536: PetscMalloc1(1, iss);
10537: MatGetOwnershipRange(A, &rstart, &rend);
10538: ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]);
10539: MPI_Comm_free(&subcomm);
10540: return 0;
10541: }
10543: /*@
10544: MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10546: If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10547: If they are not the same, uses `MatMatMatMult()`.
10549: Once the coarse grid problem is constructed, correct for interpolation operators
10550: that are not of full rank, which can legitimately happen in the case of non-nested
10551: geometric multigrid.
10553: Input Parameters:
10554: + restrct - restriction operator
10555: . dA - fine grid matrix
10556: . interpolate - interpolation operator
10557: . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10558: - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10560: Output Parameters:
10561: . A - the Galerkin coarse matrix
10563: Options Database Key:
10564: . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10566: Level: developer
10568: .seealso: `MatPtAP()`, `MatMatMatMult()`
10569: @*/
10570: PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10571: {
10572: IS zerorows;
10573: Vec diag;
10576: /* Construct the coarse grid matrix */
10577: if (interpolate == restrct) {
10578: MatPtAP(dA, interpolate, reuse, fill, A);
10579: } else {
10580: MatMatMatMult(restrct, dA, interpolate, reuse, fill, A);
10581: }
10583: /* If the interpolation matrix is not of full rank, A will have zero rows.
10584: This can legitimately happen in the case of non-nested geometric multigrid.
10585: In that event, we set the rows of the matrix to the rows of the identity,
10586: ignoring the equations (as the RHS will also be zero). */
10588: MatFindZeroRows(*A, &zerorows);
10590: if (zerorows != NULL) { /* if there are any zero rows */
10591: MatCreateVecs(*A, &diag, NULL);
10592: MatGetDiagonal(*A, diag);
10593: VecISSet(diag, zerorows, 1.0);
10594: MatDiagonalSet(*A, diag, INSERT_VALUES);
10595: VecDestroy(&diag);
10596: ISDestroy(&zerorows);
10597: }
10598: return 0;
10599: }
10601: /*@C
10602: MatSetOperation - Allows user to set a matrix operation for any matrix type
10604: Logically Collective on mat
10606: Input Parameters:
10607: + mat - the matrix
10608: . op - the name of the operation
10609: - f - the function that provides the operation
10611: Level: developer
10613: Usage:
10614: $ extern PetscErrorCode usermult(Mat,Vec,Vec);
10615: $ MatCreateXXX(comm,...&A;
10616: $ MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult;
10618: Notes:
10619: See the file include/petscmat.h for a complete list of matrix
10620: operations, which all have the form MATOP_<OPERATION>, where
10621: <OPERATION> is the name (in all capital letters) of the
10622: user interface routine (e.g., MatMult() -> MATOP_MULT).
10624: All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10625: sequence as the usual matrix interface routines, since they
10626: are intended to be accessed via the usual matrix interface
10627: routines, e.g.,
10628: $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10630: In particular each function MUST return an error code of 0 on success and
10631: nonzero on failure.
10633: This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10635: .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10636: @*/
10637: PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10638: {
10640: if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10641: (((void (**)(void))mat->ops)[op]) = f;
10642: return 0;
10643: }
10645: /*@C
10646: MatGetOperation - Gets a matrix operation for any matrix type.
10648: Not Collective
10650: Input Parameters:
10651: + mat - the matrix
10652: - op - the name of the operation
10654: Output Parameter:
10655: . f - the function that provides the operation
10657: Level: developer
10659: Usage:
10660: $ PetscErrorCode (*usermult)(Mat,Vec,Vec);
10661: $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10663: Notes:
10664: See the file include/petscmat.h for a complete list of matrix
10665: operations, which all have the form MATOP_<OPERATION>, where
10666: <OPERATION> is the name (in all capital letters) of the
10667: user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10669: This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10671: .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10672: @*/
10673: PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10674: {
10676: *f = (((void (**)(void))mat->ops)[op]);
10677: return 0;
10678: }
10680: /*@
10681: MatHasOperation - Determines whether the given matrix supports the particular operation.
10683: Not Collective
10685: Input Parameters:
10686: + mat - the matrix
10687: - op - the operation, for example, `MATOP_GET_DIAGONAL`
10689: Output Parameter:
10690: . has - either `PETSC_TRUE` or `PETSC_FALSE`
10692: Level: advanced
10694: Note:
10695: See the file include/petscmat.h for a complete list of matrix
10696: operations, which all have the form MATOP_<OPERATION>, where
10697: <OPERATION> is the name (in all capital letters) of the
10698: user-level routine. E.g., `MatNorm()` -> `MATOP_NORM`.
10700: .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10701: @*/
10702: PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10703: {
10706: if (mat->ops->hasoperation) {
10707: PetscUseTypeMethod(mat, hasoperation, op, has);
10708: } else {
10709: if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10710: else {
10711: *has = PETSC_FALSE;
10712: if (op == MATOP_CREATE_SUBMATRIX) {
10713: PetscMPIInt size;
10715: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
10716: if (size == 1) MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has);
10717: }
10718: }
10719: }
10720: return 0;
10721: }
10723: /*@
10724: MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
10726: Collective on mat
10728: Input Parameters:
10729: . mat - the matrix
10731: Output Parameter:
10732: . cong - either `PETSC_TRUE` or `PETSC_FALSE`
10734: Level: beginner
10736: .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10737: @*/
10738: PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10739: {
10743: if (!mat->rmap || !mat->cmap) {
10744: *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10745: return 0;
10746: }
10747: if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10748: PetscLayoutSetUp(mat->rmap);
10749: PetscLayoutSetUp(mat->cmap);
10750: PetscLayoutCompare(mat->rmap, mat->cmap, cong);
10751: if (*cong) mat->congruentlayouts = 1;
10752: else mat->congruentlayouts = 0;
10753: } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10754: return 0;
10755: }
10757: PetscErrorCode MatSetInf(Mat A)
10758: {
10759: PetscUseTypeMethod(A, setinf);
10760: return 0;
10761: }
10763: /*C
10764: 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
10765: and possibly removes small values from the graph structure.
10767: Collective on mat
10769: Input Parameters:
10770: + A - the matrix
10771: . sym - `PETSC_TRUE` indicates that the graph should be symmetrized
10772: . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
10773: - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
10775: Output Parameter:
10776: . graph - the resulting graph
10778: Level: advanced
10780: .seealso: `MatCreate()`, `PCGAMG`
10781: */
10782: PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
10783: {
10787: PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
10788: return 0;
10789: }