Actual source code: matrix.c
1: /*
2: This is where the abstract matrix operations are defined
3: */
5: #include <petsc/private/matimpl.h>
6: #include <petsc/private/isimpl.h>
7: #include <petsc/private/vecimpl.h>
9: /* Logging support */
10: PetscClassId MAT_CLASSID;
11: PetscClassId MAT_COLORING_CLASSID;
12: PetscClassId MAT_FDCOLORING_CLASSID;
13: PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
15: PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
16: PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
17: PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
18: PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
19: PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
20: PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
21: PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
22: PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
23: PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
24: PetscLogEvent MAT_TransposeColoringCreate;
25: PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
26: PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
27: PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
28: PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
29: PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
30: PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
31: PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
32: PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
33: PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
34: PetscLogEvent MAT_GetMultiProcBlock;
35: PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
36: PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
37: PetscLogEvent MAT_SetValuesBatch;
38: PetscLogEvent MAT_ViennaCLCopyToGPU;
39: PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
40: PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
41: PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
42: PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
43: PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
45: const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
47: /*@
48: 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,
49: for sparse matrices that already have locations it fills the locations with random numbers
51: Logically Collective on mat
53: Input Parameters:
54: + x - the matrix
55: - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and
56: it will create one internally.
58: Output Parameter:
59: . x - the matrix
61: Example of Usage:
62: .vb
63: PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64: MatSetRandom(x,rctx);
65: PetscRandomDestroy(rctx);
66: .ve
68: Level: intermediate
70: .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
71: @*/
72: PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
73: {
74: PetscRandom randObj = NULL;
79: MatCheckPreallocated(x, 1);
81: if (!rctx) {
82: MPI_Comm comm;
83: PetscObjectGetComm((PetscObject)x, &comm);
84: PetscRandomCreate(comm, &randObj);
85: PetscRandomSetType(randObj, x->defaultrandtype);
86: PetscRandomSetFromOptions(randObj);
87: rctx = randObj;
88: }
89: PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0);
90: PetscUseTypeMethod(x, setrandom, rctx);
91: PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0);
93: MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY);
94: MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY);
95: PetscRandomDestroy(&randObj);
96: return 0;
97: }
99: /*@
100: MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
102: Logically Collective on mat
104: Input Parameter:
105: . mat - the factored matrix
107: Output Parameters:
108: + pivot - the pivot value computed
109: - row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
110: the share the matrix
112: Level: advanced
114: Notes:
115: This routine does not work for factorizations done with external packages.
117: This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
119: This can be called on non-factored matrices that come from, for example, matrices used in SOR.
121: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
122: `MAT_FACTOR_NUMERIC_ZEROPIVOT`
123: @*/
124: PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
125: {
129: *pivot = mat->factorerror_zeropivot_value;
130: *row = mat->factorerror_zeropivot_row;
131: return 0;
132: }
134: /*@
135: MatFactorGetError - gets the error code from a factorization
137: Logically Collective on mat
139: Input Parameters:
140: . mat - the factored matrix
142: Output Parameter:
143: . err - the error code
145: Level: advanced
147: Note:
148: This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
150: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
151: `MatFactorError`
152: @*/
153: PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
154: {
157: *err = mat->factorerrortype;
158: return 0;
159: }
161: /*@
162: MatFactorClearError - clears the error code in a factorization
164: Logically Collective on mat
166: Input Parameter:
167: . mat - the factored matrix
169: Level: developer
171: Note:
172: This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
174: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
175: `MatGetErrorCode()`, `MatFactorError`
176: @*/
177: PetscErrorCode MatFactorClearError(Mat mat)
178: {
180: mat->factorerrortype = MAT_FACTOR_NOERROR;
181: mat->factorerror_zeropivot_value = 0.0;
182: mat->factorerror_zeropivot_row = 0;
183: return 0;
184: }
186: PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
187: {
188: Vec r, l;
189: const PetscScalar *al;
190: PetscInt i, nz, gnz, N, n;
192: MatCreateVecs(mat, &r, &l);
193: if (!cols) { /* nonzero rows */
194: MatGetSize(mat, &N, NULL);
195: MatGetLocalSize(mat, &n, NULL);
196: VecSet(l, 0.0);
197: VecSetRandom(r, NULL);
198: MatMult(mat, r, l);
199: VecGetArrayRead(l, &al);
200: } else { /* nonzero columns */
201: MatGetSize(mat, NULL, &N);
202: MatGetLocalSize(mat, NULL, &n);
203: VecSet(r, 0.0);
204: VecSetRandom(l, NULL);
205: MatMultTranspose(mat, l, r);
206: VecGetArrayRead(r, &al);
207: }
208: if (tol <= 0.0) {
209: for (i = 0, nz = 0; i < n; i++)
210: if (al[i] != 0.0) nz++;
211: } else {
212: for (i = 0, nz = 0; i < n; i++)
213: if (PetscAbsScalar(al[i]) > tol) nz++;
214: }
215: MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
216: if (gnz != N) {
217: PetscInt *nzr;
218: PetscMalloc1(nz, &nzr);
219: if (nz) {
220: if (tol < 0) {
221: for (i = 0, nz = 0; i < n; i++)
222: if (al[i] != 0.0) nzr[nz++] = i;
223: } else {
224: for (i = 0, nz = 0; i < n; i++)
225: if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
226: }
227: }
228: ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero);
229: } else *nonzero = NULL;
230: if (!cols) { /* nonzero rows */
231: VecRestoreArrayRead(l, &al);
232: } else {
233: VecRestoreArrayRead(r, &al);
234: }
235: VecDestroy(&l);
236: VecDestroy(&r);
237: return 0;
238: }
240: /*@
241: MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
243: Input Parameter:
244: . A - the matrix
246: Output Parameter:
247: . keptrows - the rows that are not completely zero
249: Note:
250: keptrows is set to NULL if all rows are nonzero.
252: Level: intermediate
254: .seealso: `Mat`, `MatFindZeroRows()`
255: @*/
256: PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
257: {
263: if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
264: else MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows);
265: return 0;
266: }
268: /*@
269: MatFindZeroRows - Locate all rows that are completely zero in the matrix
271: Input Parameter:
272: . A - the matrix
274: Output Parameter:
275: . zerorows - the rows that are completely zero
277: Note:
278: zerorows is set to NULL if no rows are zero.
280: Level: intermediate
282: .seealso: `Mat`, `MatFindNonzeroRows()`
283: @*/
284: PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
285: {
286: IS keptrows;
287: PetscInt m, n;
292: MatFindNonzeroRows(mat, &keptrows);
293: /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
294: In keeping with this convention, we set zerorows to NULL if there are no zero
295: rows. */
296: if (keptrows == NULL) {
297: *zerorows = NULL;
298: } else {
299: MatGetOwnershipRange(mat, &m, &n);
300: ISComplement(keptrows, m, n, zerorows);
301: ISDestroy(&keptrows);
302: }
303: return 0;
304: }
306: /*@
307: MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
309: Not Collective
311: Input Parameters:
312: . A - the matrix
314: Output Parameters:
315: . a - the diagonal part (which is a SEQUENTIAL matrix)
317: Notes:
318: See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
320: 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.
322: Level: advanced
324: .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
325: @*/
326: PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
327: {
332: if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
333: else {
334: PetscMPIInt size;
336: MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);
338: *a = A;
339: }
340: return 0;
341: }
343: /*@
344: MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
346: Collective on mat
348: Input Parameters:
349: . mat - the matrix
351: Output Parameter:
352: . trace - the sum of the diagonal entries
354: Level: advanced
356: .seealso: `Mat`
357: @*/
358: PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
359: {
360: Vec diag;
364: MatCreateVecs(mat, &diag, NULL);
365: MatGetDiagonal(mat, diag);
366: VecSum(diag, trace);
367: VecDestroy(&diag);
368: return 0;
369: }
371: /*@
372: MatRealPart - Zeros out the imaginary part of the matrix
374: Logically Collective on mat
376: Input Parameters:
377: . mat - the matrix
379: Level: advanced
381: .seealso: `MatImaginaryPart()`
382: @*/
383: PetscErrorCode MatRealPart(Mat mat)
384: {
389: MatCheckPreallocated(mat, 1);
390: PetscUseTypeMethod(mat, realpart);
391: return 0;
392: }
394: /*@C
395: MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
397: Collective on mat
399: Input Parameter:
400: . mat - the matrix
402: Output Parameters:
403: + nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
404: - ghosts - the global indices of the ghost points
406: Note:
407: the nghosts and ghosts are suitable to pass into `VecCreateGhost()`
409: Level: advanced
411: .seealso: `Mat`, `VecCreateGhost()`
412: @*/
413: PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
414: {
419: if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
420: else {
421: if (nghosts) *nghosts = 0;
422: if (ghosts) *ghosts = NULL;
423: }
424: return 0;
425: }
427: /*@
428: MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
430: Logically Collective on mat
432: Input Parameters:
433: . mat - the matrix
435: Level: advanced
437: .seealso: `MatRealPart()`
438: @*/
439: PetscErrorCode MatImaginaryPart(Mat mat)
440: {
445: MatCheckPreallocated(mat, 1);
446: PetscUseTypeMethod(mat, imaginarypart);
447: return 0;
448: }
450: /*@
451: MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
453: Not Collective
455: Input Parameter:
456: . mat - the matrix
458: Output Parameters:
459: + missing - is any diagonal missing
460: - dd - first diagonal entry that is missing (optional) on this process
462: Level: advanced
464: .seealso: `Mat`
465: @*/
466: PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
467: {
473: PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
474: return 0;
475: }
477: /*@C
478: MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()`
479: for each row that you get to ensure that your application does
480: not bleed memory.
482: Not Collective
484: Input Parameters:
485: + mat - the matrix
486: - row - the row to get
488: Output Parameters:
489: + ncols - if not NULL, the number of nonzeros in the row
490: . cols - if not NULL, the column numbers
491: - vals - if not NULL, the values
493: Notes:
494: This routine is provided for people who need to have direct access
495: to the structure of a matrix. We hope that we provide enough
496: high-level matrix routines that few users will need it.
498: `MatGetRow()` always returns 0-based column indices, regardless of
499: whether the internal representation is 0-based (default) or 1-based.
501: For better efficiency, set cols and/or vals to NULL if you do
502: not wish to extract these quantities.
504: The user can only examine the values extracted with `MatGetRow()`;
505: the values cannot be altered. To change the matrix entries, one
506: must use `MatSetValues()`.
508: You can only have one call to `MatGetRow()` outstanding for a particular
509: matrix at a time, per processor. `MatGetRow()` can only obtain rows
510: associated with the given processor, it cannot get rows from the
511: other processors; for that we suggest using `MatCreateSubMatrices()`, then
512: MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
513: is in the global number of rows.
515: Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
517: Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
519: Fortran Note:
520: The calling sequence from Fortran is
521: .vb
522: MatGetRow(matrix,row,ncols,cols,values,ierr)
523: Mat matrix (input)
524: integer row (input)
525: integer ncols (output)
526: integer cols(maxcols) (output)
527: double precision (or double complex) values(maxcols) output
528: .ve
529: where maxcols >= maximum nonzeros in any row of the matrix.
531: Caution:
532: Do not try to change the contents of the output arrays (cols and vals).
533: In some cases, this may corrupt the matrix.
535: Level: advanced
537: .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
538: @*/
539: PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
540: {
541: PetscInt incols;
547: MatCheckPreallocated(mat, 1);
549: PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0);
550: (*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
551: if (ncols) *ncols = incols;
552: PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0);
553: return 0;
554: }
556: /*@
557: MatConjugate - replaces the matrix values with their complex conjugates
559: Logically Collective on mat
561: Input Parameters:
562: . mat - the matrix
564: Level: advanced
566: .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
567: @*/
568: PetscErrorCode MatConjugate(Mat mat)
569: {
572: if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
573: PetscUseTypeMethod(mat, conjugate);
574: PetscObjectStateIncrease((PetscObject)mat);
575: }
576: return 0;
577: }
579: /*@C
580: MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
582: Not Collective
584: Input Parameters:
585: + mat - the matrix
586: . row - the row to get
587: . ncols, cols - the number of nonzeros and their columns
588: - vals - if nonzero the column values
590: Notes:
591: This routine should be called after you have finished examining the entries.
593: This routine zeros out ncols, cols, and vals. This is to prevent accidental
594: us of the array after it has been restored. If you pass NULL, it will
595: not zero the pointers. Use of cols or vals after `MatRestoreRow()` is invalid.
597: Fortran Notes:
598: The calling sequence from Fortran is
599: .vb
600: MatRestoreRow(matrix,row,ncols,cols,values,ierr)
601: Mat matrix (input)
602: integer row (input)
603: integer ncols (output)
604: integer cols(maxcols) (output)
605: double precision (or double complex) values(maxcols) output
606: .ve
607: Where maxcols >= maximum nonzeros in any row of the matrix.
609: In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
610: before another call to `MatGetRow()` can be made.
612: Level: advanced
614: .seealso: `MatGetRow()`
615: @*/
616: PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
617: {
621: if (!mat->ops->restorerow) return 0;
622: (*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
623: if (ncols) *ncols = 0;
624: if (cols) *cols = NULL;
625: if (vals) *vals = NULL;
626: return 0;
627: }
629: /*@
630: MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
631: You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
633: Not Collective
635: Input Parameters:
636: . mat - the matrix
638: Note:
639: 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.
641: Level: advanced
643: .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
644: @*/
645: PetscErrorCode MatGetRowUpperTriangular(Mat mat)
646: {
651: MatCheckPreallocated(mat, 1);
652: if (!mat->ops->getrowuppertriangular) return 0;
653: PetscUseTypeMethod(mat, getrowuppertriangular);
654: return 0;
655: }
657: /*@
658: MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
660: Not Collective
662: Input Parameters:
663: . mat - the matrix
665: Note:
666: This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
668: Level: advanced
670: .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()`
671: @*/
672: PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
673: {
678: MatCheckPreallocated(mat, 1);
679: if (!mat->ops->restorerowuppertriangular) return 0;
680: PetscUseTypeMethod(mat, restorerowuppertriangular);
681: return 0;
682: }
684: /*@C
685: MatSetOptionsPrefix - Sets the prefix used for searching for all
686: `Mat` options in the database.
688: Logically Collective on A
690: Input Parameters:
691: + A - the matrix
692: - prefix - the prefix to prepend to all option names
694: Notes:
695: A hyphen (-) must NOT be given at the beginning of the prefix name.
696: The first character of all runtime options is AUTOMATICALLY the hyphen.
698: This is NOT used for options for the factorization of the matrix. Normally the
699: prefix is automatically passed in from the PC calling the factorization. To set
700: it directly use `MatSetOptionsPrefixFactor()`
702: Level: advanced
704: .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
705: @*/
706: PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
707: {
709: PetscObjectSetOptionsPrefix((PetscObject)A, prefix);
710: return 0;
711: }
713: /*@C
714: MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
715: for matrices created with `MatGetFactor()`
717: Logically Collective on A
719: Input Parameters:
720: + A - the matrix
721: - prefix - the prefix to prepend to all option names for the factored matrix
723: Notes:
724: A hyphen (-) must NOT be given at the beginning of the prefix name.
725: The first character of all runtime options is AUTOMATICALLY the hyphen.
727: Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
728: it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()`
730: Level: developer
732: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
733: @*/
734: PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
735: {
737: if (prefix) {
740: if (prefix != A->factorprefix) {
741: PetscFree(A->factorprefix);
742: PetscStrallocpy(prefix, &A->factorprefix);
743: }
744: } else PetscFree(A->factorprefix);
745: return 0;
746: }
748: /*@C
749: MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
750: for matrices created with `MatGetFactor()`
752: Logically Collective on A
754: Input Parameters:
755: + A - the matrix
756: - prefix - the prefix to prepend to all option names for the factored matrix
758: Notes:
759: A hyphen (-) must NOT be given at the beginning of the prefix name.
760: The first character of all runtime options is AUTOMATICALLY the hyphen.
762: Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
763: it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()`
765: Level: developer
767: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
768: `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
769: `MatSetOptionsPrefix()`
770: @*/
771: PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
772: {
773: char *buf = A->factorprefix;
774: size_t len1, len2;
777: if (!prefix) return 0;
778: if (!buf) {
779: MatSetOptionsPrefixFactor(A, prefix);
780: return 0;
781: }
784: PetscStrlen(prefix, &len1);
785: PetscStrlen(buf, &len2);
786: PetscMalloc1(1 + len1 + len2, &A->factorprefix);
787: PetscStrcpy(A->factorprefix, buf);
788: PetscStrcat(A->factorprefix, prefix);
789: PetscFree(buf);
790: return 0;
791: }
793: /*@C
794: MatAppendOptionsPrefix - Appends to the prefix used for searching for all
795: matrix options in the database.
797: Logically Collective on A
799: Input Parameters:
800: + A - the matrix
801: - prefix - the prefix to prepend to all option names
803: Note:
804: A hyphen (-) must NOT be given at the beginning of the prefix name.
805: The first character of all runtime options is AUTOMATICALLY the hyphen.
807: Level: advanced
809: .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
810: @*/
811: PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
812: {
814: PetscObjectAppendOptionsPrefix((PetscObject)A, prefix);
815: return 0;
816: }
818: /*@C
819: MatGetOptionsPrefix - Gets the prefix used for searching for all
820: matrix options in the database.
822: Not Collective
824: Input Parameter:
825: . A - the matrix
827: Output Parameter:
828: . prefix - pointer to the prefix string used
830: Fortran Note:
831: On the fortran side, the user should pass in a string 'prefix' of
832: sufficient length to hold the prefix.
834: Level: advanced
836: .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
837: @*/
838: PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
839: {
842: PetscObjectGetOptionsPrefix((PetscObject)A, prefix);
843: return 0;
844: }
846: /*@
847: MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
849: Collective on A
851: Input Parameters:
852: . A - the matrix
854: Notes:
855: The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
857: Users can reset the preallocation to access the original memory.
859: Currently only supported for `MATMPIAIJ` and `MATSEQAIJ` matrices.
861: Level: beginner
863: .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
864: @*/
865: PetscErrorCode MatResetPreallocation(Mat A)
866: {
869: PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
870: return 0;
871: }
873: /*@
874: MatSetUp - Sets up the internal matrix data structures for later use.
876: Collective on A
878: Input Parameters:
879: . A - the matrix
881: Notes:
882: If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
884: If a suitable preallocation routine is used, this function does not need to be called.
886: See the Performance chapter of the PETSc users manual for how to preallocate matrices
888: This routine is called internally by other matrix functions when needed so rarely needs to be called by users
890: Level: intermediate
892: .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
893: @*/
894: PetscErrorCode MatSetUp(Mat A)
895: {
897: if (!((PetscObject)A)->type_name) {
898: PetscMPIInt size;
900: MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);
901: MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ);
902: }
903: if (!A->preallocated && A->ops->setup) {
904: PetscInfo(A, "Warning not preallocating matrix storage\n");
905: PetscUseTypeMethod(A, setup);
906: }
907: PetscLayoutSetUp(A->rmap);
908: PetscLayoutSetUp(A->cmap);
909: A->preallocated = PETSC_TRUE;
910: return 0;
911: }
913: #if defined(PETSC_HAVE_SAWS)
914: #include <petscviewersaws.h>
915: #endif
917: /*@C
918: MatViewFromOptions - View properties of the matrix from the options database
920: Collective on A
922: Input Parameters:
923: + A - the matrix
924: . obj - optional additional object that provides the options prefix to use
925: - name - command line option
927: Options Database:
928: . -mat_view [viewertype]:... - the viewer and its options
930: Notes:
931: .vb
932: If no value is provided ascii:stdout is used
933: ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
934: for example ascii::ascii_info prints just the information about the object not all details
935: unless :append is given filename opens in write mode, overwriting what was already there
936: binary[:[filename][:[format][:append]]] defaults to the file binaryoutput
937: draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x
938: socket[:port] defaults to the standard output port
939: saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs)
940: .ve
942: Level: intermediate
944: .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
945: @*/
946: PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
947: {
949: PetscObjectViewFromOptions((PetscObject)A, obj, name);
950: return 0;
951: }
953: /*@C
954: MatView - display information about a matrix in a variety ways
956: Collective on mat
958: Input Parameters:
959: + mat - the matrix
960: - viewer - visualization context
962: Notes:
963: The available visualization contexts include
964: + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
965: . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
966: . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
967: - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
969: The user can open alternative visualization contexts with
970: + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
971: . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
972: specified file; corresponding input uses MatLoad()
973: . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
974: an X window display
975: - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
976: Currently only the sequential dense and AIJ
977: matrix types support the Socket viewer.
979: The user can call `PetscViewerPushFormat()` to specify the output
980: format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
981: `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include
982: + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
983: . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
984: . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
985: . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
986: format common among all matrix types
987: . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
988: format (which is in many cases the same as the default)
989: . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
990: size and structure (not the matrix entries)
991: - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
992: the matrix structure
994: Options Database Keys:
995: + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
996: . -mat_view ::ascii_info_detail - Prints more detailed info
997: . -mat_view - Prints matrix in ASCII format
998: . -mat_view ::ascii_matlab - Prints matrix in Matlab format
999: . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1000: . -display <name> - Sets display name (default is host)
1001: . -draw_pause <sec> - Sets number of seconds to pause after display
1002: . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1003: . -viewer_socket_machine <machine> -
1004: . -viewer_socket_port <port> -
1005: . -mat_view binary - save matrix to file in binary format
1006: - -viewer_binary_filename <name> -
1008: Level: beginner
1010: Notes:
1011: The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1012: the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1014: In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1016: See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1017: viewer is used.
1019: See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1020: viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1022: One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1023: and then use the following mouse functions.
1024: .vb
1025: left mouse: zoom in
1026: middle mouse: zoom out
1027: right mouse: continue with the simulation
1028: .ve
1030: .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`,
1031: `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1032: @*/
1033: PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1034: {
1035: PetscInt rows, cols, rbs, cbs;
1036: PetscBool isascii, isstring, issaws;
1037: PetscViewerFormat format;
1038: PetscMPIInt size;
1042: if (!viewer) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer);
1045: MatCheckPreallocated(mat, 1);
1047: PetscViewerGetFormat(viewer, &format);
1048: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
1049: if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) return 0;
1051: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring);
1052: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
1053: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws);
1056: PetscLogEventBegin(MAT_View, mat, viewer, 0, 0);
1057: if (isascii) {
1059: PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer);
1060: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1061: MatNullSpace nullsp, transnullsp;
1063: PetscViewerASCIIPushTab(viewer);
1064: MatGetSize(mat, &rows, &cols);
1065: MatGetBlockSizes(mat, &rbs, &cbs);
1066: if (rbs != 1 || cbs != 1) {
1067: if (rbs != cbs) PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs);
1068: else PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs);
1069: } else PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols);
1070: if (mat->factortype) {
1071: MatSolverType solver;
1072: MatFactorGetSolverType(mat, &solver);
1073: PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver);
1074: }
1075: if (mat->ops->getinfo) {
1076: MatInfo info;
1077: MatGetInfo(mat, MAT_GLOBAL_SUM, &info);
1078: PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated);
1079: if (!mat->factortype) PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs);
1080: }
1081: MatGetNullSpace(mat, &nullsp);
1082: MatGetTransposeNullSpace(mat, &transnullsp);
1083: if (nullsp) PetscViewerASCIIPrintf(viewer, " has attached null space\n");
1084: if (transnullsp && transnullsp != nullsp) PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n");
1085: MatGetNearNullSpace(mat, &nullsp);
1086: if (nullsp) PetscViewerASCIIPrintf(viewer, " has attached near null space\n");
1087: PetscViewerASCIIPushTab(viewer);
1088: MatProductView(mat, viewer);
1089: PetscViewerASCIIPopTab(viewer);
1090: }
1091: } else if (issaws) {
1092: #if defined(PETSC_HAVE_SAWS)
1093: PetscMPIInt rank;
1095: PetscObjectName((PetscObject)mat);
1096: MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1097: if (!((PetscObject)mat)->amsmem && rank == 0) PetscObjectViewSAWs((PetscObject)mat, viewer);
1098: #endif
1099: } else if (isstring) {
1100: const char *type;
1101: MatGetType(mat, &type);
1102: PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type);
1103: PetscTryTypeMethod(mat, view, viewer);
1104: }
1105: if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1106: PetscViewerASCIIPushTab(viewer);
1107: PetscUseTypeMethod(mat, viewnative, viewer);
1108: PetscViewerASCIIPopTab(viewer);
1109: } else if (mat->ops->view) {
1110: PetscViewerASCIIPushTab(viewer);
1111: PetscUseTypeMethod(mat, view, viewer);
1112: PetscViewerASCIIPopTab(viewer);
1113: }
1114: if (isascii) {
1115: PetscViewerGetFormat(viewer, &format);
1116: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscViewerASCIIPopTab(viewer);
1117: }
1118: PetscLogEventEnd(MAT_View, mat, viewer, 0, 0);
1119: return 0;
1120: }
1122: #if defined(PETSC_USE_DEBUG)
1123: #include <../src/sys/totalview/tv_data_display.h>
1124: PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1125: {
1126: TV_add_row("Local rows", "int", &mat->rmap->n);
1127: TV_add_row("Local columns", "int", &mat->cmap->n);
1128: TV_add_row("Global rows", "int", &mat->rmap->N);
1129: TV_add_row("Global columns", "int", &mat->cmap->N);
1130: TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1131: return TV_format_OK;
1132: }
1133: #endif
1135: /*@C
1136: MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1137: with `MatView()`. The matrix format is determined from the options database.
1138: Generates a parallel MPI matrix if the communicator has more than one
1139: processor. The default matrix type is `MATAIJ`.
1141: Collective on mat
1143: Input Parameters:
1144: + mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1145: or some related function before a call to `MatLoad()`
1146: - viewer - binary/HDF5 file viewer
1148: Options Database Keys:
1149: Used with block matrix formats (`MATSEQBAIJ`, ...) to specify
1150: block size
1151: . -matload_block_size <bs> - set block size
1153: Level: beginner
1155: Notes:
1156: If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1157: `Mat` before calling this routine if you wish to set it from the options database.
1159: `MatLoad()` automatically loads into the options database any options
1160: given in the file filename.info where filename is the name of the file
1161: that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1162: file will be ignored if you use the -viewer_binary_skip_info option.
1164: If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1165: sets the default matrix type AIJ and sets the local and global sizes.
1166: If type and/or size is already set, then the same are used.
1168: In parallel, each processor can load a subset of rows (or the
1169: entire matrix). This routine is especially useful when a large
1170: matrix is stored on disk and only part of it is desired on each
1171: processor. For example, a parallel solver may access only some of
1172: the rows from each processor. The algorithm used here reads
1173: relatively small blocks of data rather than reading the entire
1174: matrix and then subsetting it.
1176: Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1177: Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1178: or the sequence like
1179: .vb
1180: `PetscViewer` v;
1181: `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1182: `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1183: `PetscViewerSetFromOptions`(v);
1184: `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1185: `PetscViewerFileSetName`(v,"datafile");
1186: .ve
1187: The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1188: $ -viewer_type {binary,hdf5}
1190: See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1191: and src/mat/tutorials/ex10.c with the second approach.
1193: Notes about the PETSc binary format:
1194: In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1195: is read onto rank 0 and then shipped to its destination rank, one after another.
1196: Multiple objects, both matrices and vectors, can be stored within the same file.
1197: Their PetscObject name is ignored; they are loaded in the order of their storage.
1199: Most users should not need to know the details of the binary storage
1200: format, since `MatLoad()` and `MatView()` completely hide these details.
1201: But for anyone who's interested, the standard binary matrix storage
1202: format is
1204: $ PetscInt MAT_FILE_CLASSID
1205: $ PetscInt number of rows
1206: $ PetscInt number of columns
1207: $ PetscInt total number of nonzeros
1208: $ PetscInt *number nonzeros in each row
1209: $ PetscInt *column indices of all nonzeros (starting index is zero)
1210: $ PetscScalar *values of all nonzeros
1212: PETSc automatically does the byte swapping for
1213: machines that store the bytes reversed, e.g. DEC alpha, freebsd,
1214: Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1215: read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1216: and `PetscBinaryWrite()` to see how this may be done.
1218: Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1219: In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1220: Each processor's chunk is loaded independently by its owning rank.
1221: Multiple objects, both matrices and vectors, can be stored within the same file.
1222: They are looked up by their PetscObject name.
1224: As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1225: by default the same structure and naming of the AIJ arrays and column count
1226: within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1227: $ save example.mat A b -v7.3
1228: can be directly read by this routine (see Reference 1 for details).
1229: Note that depending on your MATLAB version, this format might be a default,
1230: otherwise you can set it as default in Preferences.
1232: Unless -nocompression flag is used to save the file in MATLAB,
1233: PETSc must be configured with ZLIB package.
1235: See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1237: Current HDF5 (MAT-File) limitations:
1238: This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1240: Corresponding `MatView()` is not yet implemented.
1242: The loaded matrix is actually a transpose of the original one in MATLAB,
1243: unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1244: With this format, matrix is automatically transposed by PETSc,
1245: unless the matrix is marked as SPD or symmetric
1246: (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1248: References:
1249: . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1251: .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1252: @*/
1253: PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1254: {
1255: PetscBool flg;
1260: if (!((PetscObject)mat)->type_name) MatSetType(mat, MATAIJ);
1262: flg = PETSC_FALSE;
1263: PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL);
1264: if (flg) {
1265: MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE);
1266: MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE);
1267: }
1268: flg = PETSC_FALSE;
1269: PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL);
1270: if (flg) MatSetOption(mat, MAT_SPD, PETSC_TRUE);
1272: PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0);
1273: PetscUseTypeMethod(mat, load, viewer);
1274: PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0);
1275: return 0;
1276: }
1278: static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1279: {
1280: Mat_Redundant *redund = *redundant;
1282: if (redund) {
1283: if (redund->matseq) { /* via MatCreateSubMatrices() */
1284: ISDestroy(&redund->isrow);
1285: ISDestroy(&redund->iscol);
1286: MatDestroySubMatrices(1, &redund->matseq);
1287: } else {
1288: PetscFree2(redund->send_rank, redund->recv_rank);
1289: PetscFree(redund->sbuf_j);
1290: PetscFree(redund->sbuf_a);
1291: for (PetscInt i = 0; i < redund->nrecvs; i++) {
1292: PetscFree(redund->rbuf_j[i]);
1293: PetscFree(redund->rbuf_a[i]);
1294: }
1295: PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a);
1296: }
1298: if (redund->subcomm) PetscCommDestroy(&redund->subcomm);
1299: PetscFree(redund);
1300: }
1301: return 0;
1302: }
1304: /*@C
1305: MatDestroy - Frees space taken by a matrix.
1307: Collective on A
1309: Input Parameter:
1310: . A - the matrix
1312: Level: beginner
1314: Developer Note:
1315: Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1316: `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1317: `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1318: if changes are needed here.
1320: .seealso: `Mat`, `MatCreate()`
1321: @*/
1322: PetscErrorCode MatDestroy(Mat *A)
1323: {
1324: if (!*A) return 0;
1326: if (--((PetscObject)(*A))->refct > 0) {
1327: *A = NULL;
1328: return 0;
1329: }
1331: /* if memory was published with SAWs then destroy it */
1332: PetscObjectSAWsViewOff((PetscObject)*A);
1333: PetscTryTypeMethod((*A), destroy);
1335: PetscFree((*A)->factorprefix);
1336: PetscFree((*A)->defaultvectype);
1337: PetscFree((*A)->defaultrandtype);
1338: PetscFree((*A)->bsizes);
1339: PetscFree((*A)->solvertype);
1340: for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscFree((*A)->preferredordering[i]);
1341: if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1342: MatDestroy_Redundant(&(*A)->redundant);
1343: MatProductClear(*A);
1344: MatNullSpaceDestroy(&(*A)->nullsp);
1345: MatNullSpaceDestroy(&(*A)->transnullsp);
1346: MatNullSpaceDestroy(&(*A)->nearnullsp);
1347: MatDestroy(&(*A)->schur);
1348: PetscLayoutDestroy(&(*A)->rmap);
1349: PetscLayoutDestroy(&(*A)->cmap);
1350: PetscHeaderDestroy(A);
1351: return 0;
1352: }
1354: /*@C
1355: MatSetValues - Inserts or adds a block of values into a matrix.
1356: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1357: MUST be called after all calls to `MatSetValues()` have been completed.
1359: Not Collective
1361: Input Parameters:
1362: + mat - the matrix
1363: . v - a logically two-dimensional array of values
1364: . m, idxm - the number of rows and their global indices
1365: . n, idxn - the number of columns and their global indices
1366: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1368: Notes:
1369: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1370: `MatSetUp()` before using this routine
1372: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1374: Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1375: options cannot be mixed without intervening calls to the assembly
1376: routines.
1378: `MatSetValues()` uses 0-based row and column numbers in Fortran
1379: as well as in C.
1381: Negative indices may be passed in idxm and idxn, these rows and columns are
1382: simply ignored. This allows easily inserting element stiffness matrices
1383: with homogeneous Dirchlet boundary conditions that you don't want represented
1384: in the matrix.
1386: Efficiency Alert:
1387: The routine `MatSetValuesBlocked()` may offer much better efficiency
1388: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1390: Level: beginner
1392: Developer Note:
1393: This is labeled with C so does not automatically generate Fortran stubs and interfaces
1394: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1396: .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1397: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1398: @*/
1399: PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1400: {
1404: if (!m || !n) return 0; /* no values to insert */
1407: MatCheckPreallocated(mat, 1);
1409: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1412: if (PetscDefined(USE_DEBUG)) {
1413: PetscInt i, j;
1416: for (i = 0; i < m; i++) {
1417: for (j = 0; j < n; j++) {
1418: if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1419: #if defined(PETSC_USE_COMPLEX)
1420: 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]);
1421: #else
1422: 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]);
1423: #endif
1424: }
1425: }
1428: }
1430: if (mat->assembled) {
1431: mat->was_assembled = PETSC_TRUE;
1432: mat->assembled = PETSC_FALSE;
1433: }
1434: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1435: PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1436: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1437: return 0;
1438: }
1440: /*@C
1441: MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1442: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1443: MUST be called after all calls to `MatSetValues()` have been completed.
1445: Not Collective
1447: Input Parameters:
1448: + mat - the matrix
1449: . v - a logically two-dimensional array of values
1450: . ism - the rows to provide
1451: . isn - the columns to provide
1452: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1454: Notes:
1455: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1456: `MatSetUp()` before using this routine
1458: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1460: Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1461: options cannot be mixed without intervening calls to the assembly
1462: routines.
1464: MatSetValues() uses 0-based row and column numbers in Fortran
1465: as well as in C.
1467: Negative indices may be passed in ism and isn, these rows and columns are
1468: simply ignored. This allows easily inserting element stiffness matrices
1469: with homogeneous Dirchlet boundary conditions that you don't want represented
1470: in the matrix.
1472: Efficiency Alert:
1473: The routine `MatSetValuesBlocked()` may offer much better efficiency
1474: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1476: Level: beginner
1478: Developer Notes:
1479: This is labeled with C so does not automatically generate Fortran stubs and interfaces
1480: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1482: This is currently not optimized for any particular `ISType`
1484: .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1485: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1486: @*/
1487: PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1488: {
1489: PetscInt m, n;
1490: const PetscInt *rows, *cols;
1494: ISGetIndices(ism, &rows);
1495: ISGetIndices(isn, &cols);
1496: ISGetLocalSize(ism, &m);
1497: ISGetLocalSize(isn, &n);
1498: MatSetValues(mat, m, rows, n, cols, v, addv);
1499: ISRestoreIndices(ism, &rows);
1500: ISRestoreIndices(isn, &cols);
1501: return 0;
1502: }
1504: /*@
1505: MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1506: values into a matrix
1508: Not Collective
1510: Input Parameters:
1511: + mat - the matrix
1512: . row - the (block) row to set
1513: - v - a logically two-dimensional array of values
1515: Notes:
1516: By the values, v, are column-oriented (for the block version) and sorted
1518: All the nonzeros in the row must be provided
1520: The matrix must have previously had its column indices set
1522: The row must belong to this process
1524: Level: intermediate
1526: .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1527: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1528: @*/
1529: PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1530: {
1531: PetscInt globalrow;
1536: ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow);
1537: MatSetValuesRow(mat, globalrow, v);
1538: return 0;
1539: }
1541: /*@
1542: MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1543: values into a matrix
1545: Not Collective
1547: Input Parameters:
1548: + mat - the matrix
1549: . row - the (block) row to set
1550: - 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
1552: Notes:
1553: The values, v, are column-oriented for the block version.
1555: All the nonzeros in the row must be provided
1557: THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1559: The row must belong to this process
1561: Level: advanced
1563: .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1564: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1565: @*/
1566: PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1567: {
1571: MatCheckPreallocated(mat, 1);
1575: mat->insertmode = INSERT_VALUES;
1577: if (mat->assembled) {
1578: mat->was_assembled = PETSC_TRUE;
1579: mat->assembled = PETSC_FALSE;
1580: }
1581: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1582: PetscUseTypeMethod(mat, setvaluesrow, row, v);
1583: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1584: return 0;
1585: }
1587: /*@
1588: MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1589: Using structured grid indexing
1591: Not Collective
1593: Input Parameters:
1594: + mat - the matrix
1595: . m - number of rows being entered
1596: . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1597: . n - number of columns being entered
1598: . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1599: . v - a logically two-dimensional array of values
1600: - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1602: Notes:
1603: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1605: Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1606: options cannot be mixed without intervening calls to the assembly
1607: routines.
1609: The grid coordinates are across the entire grid, not just the local portion
1611: `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1612: as well as in C.
1614: For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1616: In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1617: or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1619: The columns and rows in the stencil passed in MUST be contained within the
1620: ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1621: if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1622: local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1623: first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1625: In Fortran idxm and idxn should be declared as
1626: $ MatStencil idxm(4,m),idxn(4,n)
1627: and the values inserted using
1628: $ idxm(MatStencil_i,1) = i
1629: $ idxm(MatStencil_j,1) = j
1630: $ idxm(MatStencil_k,1) = k
1631: $ idxm(MatStencil_c,1) = c
1632: etc
1634: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1635: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1636: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1637: `DM_BOUNDARY_PERIODIC` boundary type.
1639: 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
1640: a single value per point) you can skip filling those indices.
1642: Inspired by the structured grid interface to the HYPRE package
1643: (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1645: Efficiency Alert:
1646: The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1647: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1649: Level: beginner
1651: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1652: `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1653: @*/
1654: PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1655: {
1656: PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1657: PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1658: PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1660: if (!m || !n) return 0; /* no values to insert */
1666: if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1667: jdxm = buf;
1668: jdxn = buf + m;
1669: } else {
1670: PetscMalloc2(m, &bufm, n, &bufn);
1671: jdxm = bufm;
1672: jdxn = bufn;
1673: }
1674: for (i = 0; i < m; i++) {
1675: for (j = 0; j < 3 - sdim; j++) dxm++;
1676: tmp = *dxm++ - starts[0];
1677: for (j = 0; j < dim - 1; j++) {
1678: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1679: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1680: }
1681: if (mat->stencil.noc) dxm++;
1682: jdxm[i] = tmp;
1683: }
1684: for (i = 0; i < n; i++) {
1685: for (j = 0; j < 3 - sdim; j++) dxn++;
1686: tmp = *dxn++ - starts[0];
1687: for (j = 0; j < dim - 1; j++) {
1688: if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1689: else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1690: }
1691: if (mat->stencil.noc) dxn++;
1692: jdxn[i] = tmp;
1693: }
1694: MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv);
1695: PetscFree2(bufm, bufn);
1696: return 0;
1697: }
1699: /*@
1700: MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1701: Using structured grid indexing
1703: Not Collective
1705: Input Parameters:
1706: + mat - the matrix
1707: . m - number of rows being entered
1708: . idxm - grid coordinates for matrix rows being entered
1709: . n - number of columns being entered
1710: . idxn - grid coordinates for matrix columns being entered
1711: . v - a logically two-dimensional array of values
1712: - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1714: Notes:
1715: By default the values, v, are row-oriented and unsorted.
1716: See `MatSetOption()` for other options.
1718: Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1719: options cannot be mixed without intervening calls to the assembly
1720: routines.
1722: The grid coordinates are across the entire grid, not just the local portion
1724: `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1725: as well as in C.
1727: For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1729: In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1730: or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1732: The columns and rows in the stencil passed in MUST be contained within the
1733: ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1734: if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1735: local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1736: first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1738: In Fortran idxm and idxn should be declared as
1739: $ MatStencil idxm(4,m),idxn(4,n)
1740: and the values inserted using
1741: $ idxm(MatStencil_i,1) = i
1742: $ idxm(MatStencil_j,1) = j
1743: $ idxm(MatStencil_k,1) = k
1744: etc
1746: Negative indices may be passed in idxm and idxn, these rows and columns are
1747: simply ignored. This allows easily inserting element stiffness matrices
1748: with homogeneous Dirchlet boundary conditions that you don't want represented
1749: in the matrix.
1751: Inspired by the structured grid interface to the HYPRE package
1752: (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1754: Level: beginner
1756: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1757: `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1758: `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1759: @*/
1760: PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1761: {
1762: PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1763: PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1764: PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1766: if (!m || !n) return 0; /* no values to insert */
1773: if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1774: jdxm = buf;
1775: jdxn = buf + m;
1776: } else {
1777: PetscMalloc2(m, &bufm, n, &bufn);
1778: jdxm = bufm;
1779: jdxn = bufn;
1780: }
1781: for (i = 0; i < m; i++) {
1782: for (j = 0; j < 3 - sdim; j++) dxm++;
1783: tmp = *dxm++ - starts[0];
1784: for (j = 0; j < sdim - 1; j++) {
1785: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1786: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1787: }
1788: dxm++;
1789: jdxm[i] = tmp;
1790: }
1791: for (i = 0; i < n; i++) {
1792: for (j = 0; j < 3 - sdim; j++) dxn++;
1793: tmp = *dxn++ - starts[0];
1794: for (j = 0; j < sdim - 1; j++) {
1795: if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1796: else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1797: }
1798: dxn++;
1799: jdxn[i] = tmp;
1800: }
1801: MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv);
1802: PetscFree2(bufm, bufn);
1803: return 0;
1804: }
1806: /*@
1807: MatSetStencil - Sets the grid information for setting values into a matrix via
1808: `MatSetValuesStencil()`
1810: Not Collective
1812: Input Parameters:
1813: + mat - the matrix
1814: . dim - dimension of the grid 1, 2, or 3
1815: . dims - number of grid points in x, y, and z direction, including ghost points on your processor
1816: . starts - starting point of ghost nodes on your processor in x, y, and z direction
1817: - dof - number of degrees of freedom per node
1819: Notes:
1820: Inspired by the structured grid interface to the HYPRE package
1821: (www.llnl.gov/CASC/hyper)
1823: For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1824: user.
1826: Level: beginner
1828: .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1829: `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1830: @*/
1831: PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1832: {
1837: mat->stencil.dim = dim + (dof > 1);
1838: for (PetscInt i = 0; i < dim; i++) {
1839: mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */
1840: mat->stencil.starts[i] = starts[dim - i - 1];
1841: }
1842: mat->stencil.dims[dim] = dof;
1843: mat->stencil.starts[dim] = 0;
1844: mat->stencil.noc = (PetscBool)(dof == 1);
1845: return 0;
1846: }
1848: /*@C
1849: MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1851: Not Collective
1853: Input Parameters:
1854: + mat - the matrix
1855: . v - a logically two-dimensional array of values
1856: . m, idxm - the number of block rows and their global block indices
1857: . n, idxn - the number of block columns and their global block indices
1858: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1860: Notes:
1861: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1862: MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1864: The m and n count the NUMBER of blocks in the row direction and column direction,
1865: NOT the total number of rows/columns; for example, if the block size is 2 and
1866: you are passing in values for rows 2,3,4,5 then m would be 2 (not 4).
1867: The values in idxm would be 1 2; that is the first index for each block divided by
1868: the block size.
1870: Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1871: preallocating it).
1873: By default the values, v, are row-oriented, so the layout of
1874: v is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1876: Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1877: options cannot be mixed without intervening calls to the assembly
1878: routines.
1880: `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1881: as well as in C.
1883: Negative indices may be passed in idxm and idxn, these rows and columns are
1884: simply ignored. This allows easily inserting element stiffness matrices
1885: with homogeneous Dirchlet boundary conditions that you don't want represented
1886: in the matrix.
1888: Each time an entry is set within a sparse matrix via `MatSetValues()`,
1889: internal searching must be done to determine where to place the
1890: data in the matrix storage space. By instead inserting blocks of
1891: entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1892: reduced.
1894: Example:
1895: $ Suppose m=n=2 and block size(bs) = 2 The array is
1896: $
1897: $ 1 2 | 3 4
1898: $ 5 6 | 7 8
1899: $ - - - | - - -
1900: $ 9 10 | 11 12
1901: $ 13 14 | 15 16
1902: $
1903: $ v[] should be passed in like
1904: $ v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1905: $
1906: $ If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1907: $ v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1909: Level: intermediate
1911: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1912: @*/
1913: PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1914: {
1918: if (!m || !n) return 0; /* no values to insert */
1921: MatCheckPreallocated(mat, 1);
1922: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1924: if (PetscDefined(USE_DEBUG)) {
1927: }
1928: if (PetscDefined(USE_DEBUG)) {
1929: PetscInt rbs, cbs, M, N, i;
1930: MatGetBlockSizes(mat, &rbs, &cbs);
1931: MatGetSize(mat, &M, &N);
1934: }
1935: if (mat->assembled) {
1936: mat->was_assembled = PETSC_TRUE;
1937: mat->assembled = PETSC_FALSE;
1938: }
1939: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1940: if (mat->ops->setvaluesblocked) {
1941: PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1942: } else {
1943: PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1944: PetscInt i, j, bs, cbs;
1946: MatGetBlockSizes(mat, &bs, &cbs);
1947: if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1948: iidxm = buf;
1949: iidxn = buf + m * bs;
1950: } else {
1951: PetscMalloc2(m * bs, &bufr, n * cbs, &bufc);
1952: iidxm = bufr;
1953: iidxn = bufc;
1954: }
1955: for (i = 0; i < m; i++) {
1956: for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
1957: }
1958: if (m != n || bs != cbs || idxm != idxn) {
1959: for (i = 0; i < n; i++) {
1960: for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
1961: }
1962: } else iidxn = iidxm;
1963: MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv);
1964: PetscFree2(bufr, bufc);
1965: }
1966: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1967: return 0;
1968: }
1970: /*@C
1971: MatGetValues - Gets a block of local values from a matrix.
1973: Not Collective; can only return values that are owned by the give process
1975: Input Parameters:
1976: + mat - the matrix
1977: . v - a logically two-dimensional array for storing the values
1978: . m, idxm - the number of rows and their global indices
1979: - n, idxn - the number of columns and their global indices
1981: Notes:
1982: The user must allocate space (m*n `PetscScalar`s) for the values, v.
1983: The values, v, are then returned in a row-oriented format,
1984: analogous to that used by default in `MatSetValues()`.
1986: `MatGetValues()` uses 0-based row and column numbers in
1987: Fortran as well as in C.
1989: `MatGetValues()` requires that the matrix has been assembled
1990: with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to
1991: `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
1992: without intermediate matrix assembly.
1994: Negative row or column indices will be ignored and those locations in v[] will be
1995: left unchanged.
1997: For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
1998: That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
1999: from `MatGetOwnershipRange`(mat,&rstart,&rend).
2001: Level: advanced
2003: .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2004: @*/
2005: PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2006: {
2009: if (!m || !n) return 0;
2015: MatCheckPreallocated(mat, 1);
2017: PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2018: PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2019: PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2020: return 0;
2021: }
2023: /*@C
2024: MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2025: defined previously by `MatSetLocalToGlobalMapping()`
2027: Not Collective
2029: Input Parameters:
2030: + mat - the matrix
2031: . nrow, irow - number of rows and their local indices
2032: - ncol, icol - number of columns and their local indices
2034: Output Parameter:
2035: . y - a logically two-dimensional array of values
2037: Notes:
2038: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2040: 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,
2041: are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2042: determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2043: with `MatSetLocalToGlobalMapping()`.
2045: Developer Note:
2046: This is labelled with C so does not automatically generate Fortran stubs and interfaces
2047: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2049: Level: advanced
2051: .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2052: `MatSetValuesLocal()`, `MatGetValues()`
2053: @*/
2054: PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2055: {
2059: MatCheckPreallocated(mat, 1);
2060: if (!nrow || !ncol) return 0; /* no values to retrieve */
2063: if (PetscDefined(USE_DEBUG)) {
2066: }
2068: PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2069: if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2070: else {
2071: PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2072: if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2073: irowm = buf;
2074: icolm = buf + nrow;
2075: } else {
2076: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2077: irowm = bufr;
2078: icolm = bufc;
2079: }
2082: ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm);
2083: ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm);
2084: MatGetValues(mat, nrow, irowm, ncol, icolm, y);
2085: PetscFree2(bufr, bufc);
2086: }
2087: PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2088: return 0;
2089: }
2091: /*@
2092: MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2093: the same size. Currently, this can only be called once and creates the given matrix.
2095: Not Collective
2097: Input Parameters:
2098: + mat - the matrix
2099: . nb - the number of blocks
2100: . bs - the number of rows (and columns) in each block
2101: . rows - a concatenation of the rows for each block
2102: - v - a concatenation of logically two-dimensional arrays of values
2104: Note:
2105: `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2107: In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2109: Level: advanced
2111: .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2112: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2113: @*/
2114: PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2115: {
2120: PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2122: PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0);
2123: if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2124: else {
2125: for (PetscInt b = 0; b < nb; ++b) MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES);
2126: }
2127: PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0);
2128: return 0;
2129: }
2131: /*@
2132: MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2133: the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2134: using a local (per-processor) numbering.
2136: Not Collective
2138: Input Parameters:
2139: + x - the matrix
2140: . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2141: - cmapping - column mapping
2143: Level: intermediate
2145: Note:
2146: If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2148: .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2149: @*/
2150: PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2151: {
2156: if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2157: else {
2158: PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping);
2159: PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping);
2160: }
2161: return 0;
2162: }
2164: /*@
2165: MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2167: Not Collective
2169: Input Parameter:
2170: . A - the matrix
2172: Output Parameters:
2173: + rmapping - row mapping
2174: - cmapping - column mapping
2176: Level: advanced
2178: .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2179: @*/
2180: PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2181: {
2184: if (rmapping) {
2186: *rmapping = A->rmap->mapping;
2187: }
2188: if (cmapping) {
2190: *cmapping = A->cmap->mapping;
2191: }
2192: return 0;
2193: }
2195: /*@
2196: MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2198: Logically Collective on A
2200: Input Parameters:
2201: + A - the matrix
2202: . rmap - row layout
2203: - cmap - column layout
2205: Level: advanced
2207: Note:
2208: The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2210: .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2211: @*/
2212: PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2213: {
2215: PetscLayoutReference(rmap, &A->rmap);
2216: PetscLayoutReference(cmap, &A->cmap);
2217: return 0;
2218: }
2220: /*@
2221: MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2223: Not Collective
2225: Input Parameter:
2226: . A - the matrix
2228: Output Parameters:
2229: + rmap - row layout
2230: - cmap - column layout
2232: Level: advanced
2234: .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2235: @*/
2236: PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2237: {
2240: if (rmap) {
2242: *rmap = A->rmap;
2243: }
2244: if (cmap) {
2246: *cmap = A->cmap;
2247: }
2248: return 0;
2249: }
2251: /*@C
2252: MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2253: using a local numbering of the nodes.
2255: Not Collective
2257: Input Parameters:
2258: + mat - the matrix
2259: . nrow, irow - number of rows and their local indices
2260: . ncol, icol - number of columns and their local indices
2261: . y - a logically two-dimensional array of values
2262: - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2264: Notes:
2265: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2266: `MatSetUp()` before using this routine
2268: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2270: Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2271: options cannot be mixed without intervening calls to the assembly
2272: routines.
2274: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2275: MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2277: Level: intermediate
2279: Developer Note:
2280: This is labeled with C so does not automatically generate Fortran stubs and interfaces
2281: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2283: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2284: `MatGetValuesLocal()`
2285: @*/
2286: PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2287: {
2291: MatCheckPreallocated(mat, 1);
2292: if (!nrow || !ncol) return 0; /* no values to insert */
2295: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2297: if (PetscDefined(USE_DEBUG)) {
2300: }
2302: if (mat->assembled) {
2303: mat->was_assembled = PETSC_TRUE;
2304: mat->assembled = PETSC_FALSE;
2305: }
2306: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2307: if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2308: else {
2309: PetscInt buf[8192], *bufr = NULL, *bufc = NULL;
2310: const PetscInt *irowm, *icolm;
2312: if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2313: bufr = buf;
2314: bufc = buf + nrow;
2315: irowm = bufr;
2316: icolm = bufc;
2317: } else {
2318: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2319: irowm = bufr;
2320: icolm = bufc;
2321: }
2322: if (mat->rmap->mapping) ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr);
2323: else irowm = irow;
2324: if (mat->cmap->mapping) {
2325: if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2326: ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc);
2327: } else icolm = irowm;
2328: } else icolm = icol;
2329: MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv);
2330: if (bufr != buf) PetscFree2(bufr, bufc);
2331: }
2332: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2333: return 0;
2334: }
2336: /*@C
2337: MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2338: using a local ordering of the nodes a block at a time.
2340: Not Collective
2342: Input Parameters:
2343: + x - the matrix
2344: . nrow, irow - number of rows and their local indices
2345: . ncol, icol - number of columns and their local indices
2346: . y - a logically two-dimensional array of values
2347: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2349: Notes:
2350: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2351: `MatSetUp()` before using this routine
2353: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2354: before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2356: Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2357: options cannot be mixed without intervening calls to the assembly
2358: routines.
2360: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2361: MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2363: Level: intermediate
2365: Developer Note:
2366: This is labeled with C so does not automatically generate Fortran stubs and interfaces
2367: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2369: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2370: `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2371: @*/
2372: PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2373: {
2377: MatCheckPreallocated(mat, 1);
2378: if (!nrow || !ncol) return 0; /* no values to insert */
2381: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2383: if (PetscDefined(USE_DEBUG)) {
2386: }
2388: if (mat->assembled) {
2389: mat->was_assembled = PETSC_TRUE;
2390: mat->assembled = PETSC_FALSE;
2391: }
2392: if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2393: PetscInt irbs, rbs;
2394: MatGetBlockSizes(mat, &rbs, NULL);
2395: ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs);
2397: }
2398: if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2399: PetscInt icbs, cbs;
2400: MatGetBlockSizes(mat, NULL, &cbs);
2401: ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs);
2403: }
2404: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2405: if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2406: else {
2407: PetscInt buf[8192], *bufr = NULL, *bufc = NULL;
2408: const PetscInt *irowm, *icolm;
2410: if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2411: bufr = buf;
2412: bufc = buf + nrow;
2413: irowm = bufr;
2414: icolm = bufc;
2415: } else {
2416: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2417: irowm = bufr;
2418: icolm = bufc;
2419: }
2420: if (mat->rmap->mapping) ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr);
2421: else irowm = irow;
2422: if (mat->cmap->mapping) {
2423: if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2424: ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc);
2425: } else icolm = irowm;
2426: } else icolm = icol;
2427: MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv);
2428: if (bufr != buf) PetscFree2(bufr, bufc);
2429: }
2430: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2431: return 0;
2432: }
2434: /*@
2435: MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2437: Collective on mat
2439: Input Parameters:
2440: + mat - the matrix
2441: - x - the vector to be multiplied
2443: Output Parameters:
2444: . y - the result
2446: Note:
2447: The vectors x and y cannot be the same. I.e., one cannot
2448: call `MatMultDiagonalBlock`(A,y,y).
2450: Level: developer
2452: .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2453: @*/
2454: PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2455: {
2464: MatCheckPreallocated(mat, 1);
2466: PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2467: PetscObjectStateIncrease((PetscObject)y);
2468: return 0;
2469: }
2471: /* --------------------------------------------------------*/
2472: /*@
2473: MatMult - Computes the matrix-vector product, y = Ax.
2475: Neighbor-wise Collective on mat
2477: Input Parameters:
2478: + mat - the matrix
2479: - x - the vector to be multiplied
2481: Output Parameters:
2482: . y - the result
2484: Note:
2485: The vectors x and y cannot be the same. I.e., one cannot
2486: call `MatMult`(A,y,y).
2488: Level: beginner
2490: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2491: @*/
2492: PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2493: {
2505: VecSetErrorIfLocked(y, 3);
2506: if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2507: MatCheckPreallocated(mat, 1);
2509: VecLockReadPush(x);
2510: PetscLogEventBegin(MAT_Mult, mat, x, y, 0);
2511: PetscUseTypeMethod(mat, mult, x, y);
2512: PetscLogEventEnd(MAT_Mult, mat, x, y, 0);
2513: if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2514: VecLockReadPop(x);
2515: return 0;
2516: }
2518: /*@
2519: MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2521: Neighbor-wise Collective on mat
2523: Input Parameters:
2524: + mat - the matrix
2525: - x - the vector to be multiplied
2527: Output Parameters:
2528: . y - the result
2530: Notes:
2531: The vectors x and y cannot be the same. I.e., one cannot
2532: call `MatMultTranspose`(A,y,y).
2534: For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2535: use `MatMultHermitianTranspose()`
2537: Level: beginner
2539: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2540: @*/
2541: PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2542: {
2543: PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2557: if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2558: MatCheckPreallocated(mat, 1);
2560: if (!mat->ops->multtranspose) {
2561: if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2563: } else op = mat->ops->multtranspose;
2564: PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0);
2565: VecLockReadPush(x);
2566: (*op)(mat, x, y);
2567: VecLockReadPop(x);
2568: PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0);
2569: PetscObjectStateIncrease((PetscObject)y);
2570: if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2571: return 0;
2572: }
2574: /*@
2575: MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2577: Neighbor-wise Collective on mat
2579: Input Parameters:
2580: + mat - the matrix
2581: - x - the vector to be multilplied
2583: Output Parameters:
2584: . y - the result
2586: Notes:
2587: The vectors x and y cannot be the same. I.e., one cannot
2588: call `MatMultHermitianTranspose`(A,y,y).
2590: Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2592: For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2594: Level: beginner
2596: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2597: @*/
2598: PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2599: {
2612: MatCheckPreallocated(mat, 1);
2614: PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0);
2615: #if defined(PETSC_USE_COMPLEX)
2616: if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2617: VecLockReadPush(x);
2618: if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2619: else PetscUseTypeMethod(mat, mult, x, y);
2620: VecLockReadPop(x);
2621: } else {
2622: Vec w;
2623: VecDuplicate(x, &w);
2624: VecCopy(x, w);
2625: VecConjugate(w);
2626: MatMultTranspose(mat, w, y);
2627: VecDestroy(&w);
2628: VecConjugate(y);
2629: }
2630: PetscObjectStateIncrease((PetscObject)y);
2631: #else
2632: MatMultTranspose(mat, x, y);
2633: #endif
2634: PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0);
2635: return 0;
2636: }
2638: /*@
2639: MatMultAdd - Computes v3 = v2 + A * v1.
2641: Neighbor-wise Collective on mat
2643: Input Parameters:
2644: + mat - the matrix
2645: - v1, v2 - the vectors
2647: Output Parameters:
2648: . v3 - the result
2650: Note:
2651: The vectors v1 and v3 cannot be the same. I.e., one cannot
2652: call `MatMultAdd`(A,v1,v2,v1).
2654: Level: beginner
2656: .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2657: @*/
2658: PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2659: {
2674: MatCheckPreallocated(mat, 1);
2676: PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3);
2677: VecLockReadPush(v1);
2678: PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2679: VecLockReadPop(v1);
2680: PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3);
2681: PetscObjectStateIncrease((PetscObject)v3);
2682: return 0;
2683: }
2685: /*@
2686: MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2688: Neighbor-wise Collective on mat
2690: Input Parameters:
2691: + mat - the matrix
2692: - v1, v2 - the vectors
2694: Output Parameters:
2695: . v3 - the result
2697: Note:
2698: The vectors v1 and v3 cannot be the same. I.e., one cannot
2699: call `MatMultTransposeAdd`(A,v1,v2,v1).
2701: Level: beginner
2703: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2704: @*/
2705: PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2706: {
2707: PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2722: MatCheckPreallocated(mat, 1);
2724: PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3);
2725: VecLockReadPush(v1);
2726: (*op)(mat, v1, v2, v3);
2727: VecLockReadPop(v1);
2728: PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3);
2729: PetscObjectStateIncrease((PetscObject)v3);
2730: return 0;
2731: }
2733: /*@
2734: MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2736: Neighbor-wise Collective on mat
2738: Input Parameters:
2739: + mat - the matrix
2740: - v1, v2 - the vectors
2742: Output Parameters:
2743: . v3 - the result
2745: Note:
2746: The vectors v1 and v3 cannot be the same. I.e., one cannot
2747: call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2749: Level: beginner
2751: .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2752: @*/
2753: PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2754: {
2767: MatCheckPreallocated(mat, 1);
2769: PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2770: VecLockReadPush(v1);
2771: if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2772: else {
2773: Vec w, z;
2774: VecDuplicate(v1, &w);
2775: VecCopy(v1, w);
2776: VecConjugate(w);
2777: VecDuplicate(v3, &z);
2778: MatMultTranspose(mat, w, z);
2779: VecDestroy(&w);
2780: VecConjugate(z);
2781: if (v2 != v3) {
2782: VecWAXPY(v3, 1.0, v2, z);
2783: } else {
2784: VecAXPY(v3, 1.0, z);
2785: }
2786: VecDestroy(&z);
2787: }
2788: VecLockReadPop(v1);
2789: PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2790: PetscObjectStateIncrease((PetscObject)v3);
2791: return 0;
2792: }
2794: /*@C
2795: MatGetFactorType - gets the type of factorization it is
2797: Not Collective
2799: Input Parameters:
2800: . mat - the matrix
2802: Output Parameters:
2803: . 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`
2805: Level: intermediate
2807: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2808: `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2809: @*/
2810: PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2811: {
2815: *t = mat->factortype;
2816: return 0;
2817: }
2819: /*@C
2820: MatSetFactorType - sets the type of factorization it is
2822: Logically Collective on mat
2824: Input Parameters:
2825: + mat - the matrix
2826: - 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`
2828: Level: intermediate
2830: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2831: `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2832: @*/
2833: PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2834: {
2837: mat->factortype = t;
2838: return 0;
2839: }
2841: /* ------------------------------------------------------------*/
2842: /*@C
2843: MatGetInfo - Returns information about matrix storage (number of
2844: nonzeros, memory, etc.).
2846: Collective on mat if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2848: Input Parameter:
2849: . mat - the matrix
2851: Output Parameters:
2852: + flag - flag indicating the type of parameters to be returned
2853: (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors,
2854: MAT_GLOBAL_SUM - sum over all processors)
2855: - info - matrix information context
2857: Notes:
2858: The `MatInfo` context contains a variety of matrix data, including
2859: number of nonzeros allocated and used, number of mallocs during
2860: matrix assembly, etc. Additional information for factored matrices
2861: is provided (such as the fill ratio, number of mallocs during
2862: factorization, etc.). Much of this info is printed to `PETSC_STDOUT`
2863: when using the runtime options
2864: $ -info -mat_view ::ascii_info
2866: Example for C/C++ Users:
2867: See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2868: data within the MatInfo context. For example,
2869: .vb
2870: MatInfo info;
2871: Mat A;
2872: double mal, nz_a, nz_u;
2874: MatGetInfo(A,MAT_LOCAL,&info);
2875: mal = info.mallocs;
2876: nz_a = info.nz_allocated;
2877: .ve
2879: Example for Fortran Users:
2880: Fortran users should declare info as a double precision
2881: array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2882: of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2883: a complete list of parameter names.
2884: .vb
2885: double precision info(MAT_INFO_SIZE)
2886: double precision mal, nz_a
2887: Mat A
2888: integer ierr
2890: call MatGetInfo(A,MAT_LOCAL,info,ierr)
2891: mal = info(MAT_INFO_MALLOCS)
2892: nz_a = info(MAT_INFO_NZ_ALLOCATED)
2893: .ve
2895: Level: intermediate
2897: Developer Note: fortran interface is not autogenerated as the f90
2898: interface definition cannot be generated correctly [due to MatInfo]
2900: .seealso: `MatInfo`, `MatStashGetInfo()`
2901: @*/
2902: PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2903: {
2907: MatCheckPreallocated(mat, 1);
2908: PetscUseTypeMethod(mat, getinfo, flag, info);
2909: return 0;
2910: }
2912: /*
2913: This is used by external packages where it is not easy to get the info from the actual
2914: matrix factorization.
2915: */
2916: PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2917: {
2918: PetscMemzero(info, sizeof(MatInfo));
2919: return 0;
2920: }
2922: /* ----------------------------------------------------------*/
2924: /*@C
2925: MatLUFactor - Performs in-place LU factorization of matrix.
2927: Collective on mat
2929: Input Parameters:
2930: + mat - the matrix
2931: . row - row permutation
2932: . col - column permutation
2933: - info - options for factorization, includes
2934: $ fill - expected fill as ratio of original fill.
2935: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2936: $ Run with the option -info to determine an optimal value to use
2938: Notes:
2939: Most users should employ the `KSP` interface for linear solvers
2940: instead of working directly with matrix algebra routines such as this.
2941: See, e.g., `KSPCreate()`.
2943: This changes the state of the matrix to a factored matrix; it cannot be used
2944: for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
2946: This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
2947: when not using `KSP`.
2949: Level: developer
2951: Developer Note:
2952: The Fortran interface is not autogenerated as the f90
2953: interface definition cannot be generated correctly [due to `MatFactorInfo`]
2955: .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2956: `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2957: @*/
2958: PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
2959: {
2960: MatFactorInfo tinfo;
2969: MatCheckPreallocated(mat, 1);
2970: if (!info) {
2971: MatFactorInfoInitialize(&tinfo);
2972: info = &tinfo;
2973: }
2975: PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0);
2976: PetscUseTypeMethod(mat, lufactor, row, col, info);
2977: PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0);
2978: PetscObjectStateIncrease((PetscObject)mat);
2979: return 0;
2980: }
2982: /*@C
2983: MatILUFactor - Performs in-place ILU factorization of matrix.
2985: Collective on mat
2987: Input Parameters:
2988: + mat - the matrix
2989: . row - row permutation
2990: . col - column permutation
2991: - info - structure containing
2992: $ levels - number of levels of fill.
2993: $ expected fill - as ratio of original fill.
2994: $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices
2995: missing diagonal entries)
2997: Notes:
2998: Most users should employ the `KSP` interface for linear solvers
2999: instead of working directly with matrix algebra routines such as this.
3000: See, e.g., `KSPCreate()`.
3002: Probably really in-place only when level of fill is zero, otherwise allocates
3003: new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3004: when not using `KSP`.
3006: Level: developer
3008: Developer Note:
3009: The Fortran interface is not autogenerated as the f90
3010: interface definition cannot be generated correctly [due to MatFactorInfo]
3012: .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3013: @*/
3014: PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3015: {
3024: MatCheckPreallocated(mat, 1);
3026: PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0);
3027: PetscUseTypeMethod(mat, ilufactor, row, col, info);
3028: PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0);
3029: PetscObjectStateIncrease((PetscObject)mat);
3030: return 0;
3031: }
3033: /*@C
3034: MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3035: Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3037: Collective on fact
3039: Input Parameters:
3040: + fact - the factor matrix obtained with `MatGetFactor()`
3041: . mat - the matrix
3042: . row, col - row and column permutations
3043: - info - options for factorization, includes
3044: .vb
3045: fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3046: dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3047: .ve
3049: Notes:
3050: See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3052: Most users should employ the simplified `KSP` interface for linear solvers
3053: instead of working directly with matrix algebra routines such as this.
3054: See, e.g., `KSPCreate()`.
3056: Level: developer
3058: Developer Note:
3059: The Fortran interface is not autogenerated as the f90
3060: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3062: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3063: @*/
3064: PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3065: {
3066: MatFactorInfo tinfo;
3076: if (!(fact)->ops->lufactorsymbolic) {
3077: MatSolverType stype;
3078: MatFactorGetSolverType(fact, &stype);
3079: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3080: }
3081: MatCheckPreallocated(mat, 2);
3082: if (!info) {
3083: MatFactorInfoInitialize(&tinfo);
3084: info = &tinfo;
3085: }
3087: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0);
3088: (fact->ops->lufactorsymbolic)(fact, mat, row, col, info);
3089: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0);
3090: PetscObjectStateIncrease((PetscObject)fact);
3091: return 0;
3092: }
3094: /*@C
3095: MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3096: Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3098: Collective on fact
3100: Input Parameters:
3101: + fact - the factor matrix obtained with `MatGetFactor()`
3102: . mat - the matrix
3103: - info - options for factorization
3105: Notes:
3106: See `MatLUFactor()` for in-place factorization. See
3107: `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3109: Most users should employ the `KSP` interface for linear solvers
3110: instead of working directly with matrix algebra routines such as this.
3111: See, e.g., `KSPCreate()`.
3113: Level: developer
3115: Developer Note:
3116: The Fortran interface is not autogenerated as the f90
3117: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3119: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3120: @*/
3121: PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3122: {
3123: MatFactorInfo tinfo;
3131: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3134: MatCheckPreallocated(mat, 2);
3135: if (!info) {
3136: MatFactorInfoInitialize(&tinfo);
3137: info = &tinfo;
3138: }
3140: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0);
3141: else PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0);
3142: (fact->ops->lufactornumeric)(fact, mat, info);
3143: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0);
3144: else PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0);
3145: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3146: PetscObjectStateIncrease((PetscObject)fact);
3147: return 0;
3148: }
3150: /*@C
3151: MatCholeskyFactor - Performs in-place Cholesky factorization of a
3152: symmetric matrix.
3154: Collective on mat
3156: Input Parameters:
3157: + mat - the matrix
3158: . perm - row and column permutations
3159: - f - expected fill as ratio of original fill
3161: Notes:
3162: See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`,
3163: `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3165: Most users should employ the `KSP` interface for linear solvers
3166: instead of working directly with matrix algebra routines such as this.
3167: See, e.g., `KSPCreate()`.
3169: Level: developer
3171: Developer Note:
3172: The Fortran interface is not autogenerated as the f90
3173: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3175: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3176: `MatGetOrdering()`
3177: @*/
3178: PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3179: {
3180: MatFactorInfo tinfo;
3189: MatCheckPreallocated(mat, 1);
3190: if (!info) {
3191: MatFactorInfoInitialize(&tinfo);
3192: info = &tinfo;
3193: }
3195: PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0);
3196: PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3197: PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0);
3198: PetscObjectStateIncrease((PetscObject)mat);
3199: return 0;
3200: }
3202: /*@C
3203: MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3204: of a symmetric matrix.
3206: Collective on fact
3208: Input Parameters:
3209: + fact - the factor matrix obtained with `MatGetFactor()`
3210: . mat - the matrix
3211: . perm - row and column permutations
3212: - info - options for factorization, includes
3213: $ fill - expected fill as ratio of original fill.
3214: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3215: $ Run with the option -info to determine an optimal value to use
3217: Notes:
3218: See `MatLUFactorSymbolic()` for the nonsymmetric case. See also
3219: `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3221: Most users should employ the `KSP` interface for linear solvers
3222: instead of working directly with matrix algebra routines such as this.
3223: See, e.g., `KSPCreate()`.
3225: Level: developer
3227: Developer Note:
3228: The Fortran interface is not autogenerated as the f90
3229: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3231: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3232: `MatGetOrdering()`
3233: @*/
3234: PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3235: {
3236: MatFactorInfo tinfo;
3246: if (!(fact)->ops->choleskyfactorsymbolic) {
3247: MatSolverType stype;
3248: MatFactorGetSolverType(fact, &stype);
3249: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3250: }
3251: MatCheckPreallocated(mat, 2);
3252: if (!info) {
3253: MatFactorInfoInitialize(&tinfo);
3254: info = &tinfo;
3255: }
3257: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3258: (fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info);
3259: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3260: PetscObjectStateIncrease((PetscObject)fact);
3261: return 0;
3262: }
3264: /*@C
3265: MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3266: of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3267: `MatCholeskyFactorSymbolic()`.
3269: Collective on fact
3271: Input Parameters:
3272: + fact - the factor matrix obtained with `MatGetFactor()`
3273: . mat - the initial matrix
3274: . info - options for factorization
3275: - fact - the symbolic factor of mat
3277: Note:
3278: Most users should employ the `KSP` interface for linear solvers
3279: instead of working directly with matrix algebra routines such as this.
3280: See, e.g., `KSPCreate()`.
3282: Level: developer
3284: Developer Note:
3285: The Fortran interface is not autogenerated as the f90
3286: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3288: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3289: @*/
3290: PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3291: {
3292: MatFactorInfo tinfo;
3301: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3302: MatCheckPreallocated(mat, 2);
3303: if (!info) {
3304: MatFactorInfoInitialize(&tinfo);
3305: info = &tinfo;
3306: }
3308: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3309: else PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0);
3310: (fact->ops->choleskyfactornumeric)(fact, mat, info);
3311: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3312: else PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0);
3313: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3314: PetscObjectStateIncrease((PetscObject)fact);
3315: return 0;
3316: }
3318: /*@
3319: MatQRFactor - Performs in-place QR factorization of matrix.
3321: Collective on mat
3323: Input Parameters:
3324: + mat - the matrix
3325: . col - column permutation
3326: - info - options for factorization, includes
3327: $ fill - expected fill as ratio of original fill.
3328: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3329: $ Run with the option -info to determine an optimal value to use
3331: Notes:
3332: Most users should employ the `KSP` interface for linear solvers
3333: instead of working directly with matrix algebra routines such as this.
3334: See, e.g., `KSPCreate()`.
3336: This changes the state of the matrix to a factored matrix; it cannot be used
3337: for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3339: Level: developer
3341: Developer Note:
3342: The Fortran interface is not autogenerated as the f90
3343: interface definition cannot be generated correctly [due to MatFactorInfo]
3345: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3346: `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3347: @*/
3348: PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3349: {
3356: MatCheckPreallocated(mat, 1);
3357: PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0);
3358: PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3359: PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0);
3360: PetscObjectStateIncrease((PetscObject)mat);
3361: return 0;
3362: }
3364: /*@
3365: MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3366: Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3368: Collective on fact
3370: Input Parameters:
3371: + fact - the factor matrix obtained with `MatGetFactor()`
3372: . mat - the matrix
3373: . col - column permutation
3374: - info - options for factorization, includes
3375: $ fill - expected fill as ratio of original fill.
3376: $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3377: $ Run with the option -info to determine an optimal value to use
3379: Most users should employ the `KSP` interface for linear solvers
3380: instead of working directly with matrix algebra routines such as this.
3381: See, e.g., `KSPCreate()`.
3383: Level: developer
3385: Developer Note:
3386: The Fortran interface is not autogenerated as the f90
3387: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3389: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3390: @*/
3391: PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3392: {
3393: MatFactorInfo tinfo;
3402: MatCheckPreallocated(mat, 2);
3403: if (!info) {
3404: MatFactorInfoInitialize(&tinfo);
3405: info = &tinfo;
3406: }
3408: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0);
3409: PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3410: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0);
3411: PetscObjectStateIncrease((PetscObject)fact);
3412: return 0;
3413: }
3415: /*@
3416: MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3417: Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3419: Collective on fact
3421: Input Parameters:
3422: + fact - the factor matrix obtained with `MatGetFactor()`
3423: . mat - the matrix
3424: - info - options for factorization
3426: Notes:
3427: See `MatQRFactor()` for in-place factorization.
3429: Most users should employ the `KSP` interface for linear solvers
3430: instead of working directly with matrix algebra routines such as this.
3431: See, e.g., `KSPCreate()`.
3433: Level: developer
3435: Developer Note:
3436: The Fortran interface is not autogenerated as the f90
3437: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3439: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3440: @*/
3441: PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3442: {
3443: MatFactorInfo tinfo;
3451: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3453: MatCheckPreallocated(mat, 2);
3454: if (!info) {
3455: MatFactorInfoInitialize(&tinfo);
3456: info = &tinfo;
3457: }
3459: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0);
3460: else PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0);
3461: PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3462: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0);
3463: else PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0);
3464: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3465: PetscObjectStateIncrease((PetscObject)fact);
3466: return 0;
3467: }
3469: /* ----------------------------------------------------------------*/
3470: /*@
3471: MatSolve - Solves A x = b, given a factored matrix.
3473: Neighbor-wise Collective on mat
3475: Input Parameters:
3476: + mat - the factored matrix
3477: - b - the right-hand-side vector
3479: Output Parameter:
3480: . x - the result vector
3482: Notes:
3483: The vectors b and x cannot be the same. I.e., one cannot
3484: call `MatSolve`(A,x,x).
3486: Most users should employ the `KSP` interface for linear solvers
3487: instead of working directly with matrix algebra routines such as this.
3488: See, e.g., `KSPCreate()`.
3490: Level: developer
3492: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3493: @*/
3494: PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3495: {
3506: if (!mat->rmap->N && !mat->cmap->N) return 0;
3507: MatCheckPreallocated(mat, 1);
3509: PetscLogEventBegin(MAT_Solve, mat, b, x, 0);
3510: if (mat->factorerrortype) {
3511: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3512: VecSetInf(x);
3513: } else PetscUseTypeMethod(mat, solve, b, x);
3514: PetscLogEventEnd(MAT_Solve, mat, b, x, 0);
3515: PetscObjectStateIncrease((PetscObject)x);
3516: return 0;
3517: }
3519: static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3520: {
3521: Vec b, x;
3522: PetscInt N, i;
3523: PetscErrorCode (*f)(Mat, Vec, Vec);
3524: PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3526: if (A->factorerrortype) {
3527: PetscInfo(A, "MatFactorError %d\n", A->factorerrortype);
3528: MatSetInf(X);
3529: return 0;
3530: }
3531: f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3533: MatBoundToCPU(A, &Abound);
3534: if (!Abound) {
3535: PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "");
3536: PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "");
3537: }
3538: if (Bneedconv) MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B);
3539: if (Xneedconv) MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X);
3540: MatGetSize(B, NULL, &N);
3541: for (i = 0; i < N; i++) {
3542: MatDenseGetColumnVecRead(B, i, &b);
3543: MatDenseGetColumnVecWrite(X, i, &x);
3544: (*f)(A, b, x);
3545: MatDenseRestoreColumnVecWrite(X, i, &x);
3546: MatDenseRestoreColumnVecRead(B, i, &b);
3547: }
3548: if (Bneedconv) MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B);
3549: if (Xneedconv) MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X);
3550: return 0;
3551: }
3553: /*@
3554: MatMatSolve - Solves A X = B, given a factored matrix.
3556: Neighbor-wise Collective on A
3558: Input Parameters:
3559: + A - the factored matrix
3560: - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3562: Output Parameter:
3563: . X - the result matrix (dense matrix)
3565: Note:
3566: If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO;
3567: otherwise, B and X cannot be the same.
3569: Level: developer
3571: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3572: @*/
3573: PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3574: {
3584: if (!A->rmap->N && !A->cmap->N) return 0;
3586: MatCheckPreallocated(A, 1);
3588: PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3589: if (!A->ops->matsolve) {
3590: PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name);
3591: MatMatSolve_Basic(A, B, X, PETSC_FALSE);
3592: } else PetscUseTypeMethod(A, matsolve, B, X);
3593: PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3594: PetscObjectStateIncrease((PetscObject)X);
3595: return 0;
3596: }
3598: /*@
3599: MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3601: Neighbor-wise Collective on A
3603: Input Parameters:
3604: + A - the factored matrix
3605: - B - the right-hand-side matrix (`MATDENSE` matrix)
3607: Output Parameter:
3608: . X - the result matrix (dense matrix)
3610: Note:
3611: The matrices B and X cannot be the same. I.e., one cannot
3612: call `MatMatSolveTranspose`(A,X,X).
3614: Level: developer
3616: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3617: @*/
3618: PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3619: {
3631: if (!A->rmap->N && !A->cmap->N) return 0;
3633: MatCheckPreallocated(A, 1);
3635: PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3636: if (!A->ops->matsolvetranspose) {
3637: PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name);
3638: MatMatSolve_Basic(A, B, X, PETSC_TRUE);
3639: } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3640: PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3641: PetscObjectStateIncrease((PetscObject)X);
3642: return 0;
3643: }
3645: /*@
3646: MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3648: Neighbor-wise Collective on A
3650: Input Parameters:
3651: + A - the factored matrix
3652: - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3654: Output Parameter:
3655: . X - the result matrix (dense matrix)
3657: Note:
3658: 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
3659: format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3661: Level: developer
3663: .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3664: @*/
3665: PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3666: {
3678: if (!A->rmap->N && !A->cmap->N) return 0;
3680: MatCheckPreallocated(A, 1);
3682: PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0);
3683: PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3684: PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0);
3685: PetscObjectStateIncrease((PetscObject)X);
3686: return 0;
3687: }
3689: /*@
3690: MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3691: U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3693: Neighbor-wise Collective on mat
3695: Input Parameters:
3696: + mat - the factored matrix
3697: - b - the right-hand-side vector
3699: Output Parameter:
3700: . x - the result vector
3702: Notes:
3703: `MatSolve()` should be used for most applications, as it performs
3704: a forward solve followed by a backward solve.
3706: The vectors b and x cannot be the same, i.e., one cannot
3707: call `MatForwardSolve`(A,x,x).
3709: For matrix in `MATSEQBAIJ` format with block size larger than 1,
3710: the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3711: `MatForwardSolve()` solves U^T*D y = b, and
3712: `MatBackwardSolve()` solves U x = y.
3713: Thus they do not provide a symmetric preconditioner.
3715: Level: developer
3717: .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3718: @*/
3719: PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3720: {
3731: if (!mat->rmap->N && !mat->cmap->N) return 0;
3732: MatCheckPreallocated(mat, 1);
3734: PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0);
3735: PetscUseTypeMethod(mat, forwardsolve, b, x);
3736: PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0);
3737: PetscObjectStateIncrease((PetscObject)x);
3738: return 0;
3739: }
3741: /*@
3742: MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3743: D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3745: Neighbor-wise Collective on mat
3747: Input Parameters:
3748: + mat - the factored matrix
3749: - b - the right-hand-side vector
3751: Output Parameter:
3752: . x - the result vector
3754: Notes:
3755: `MatSolve()` should be used for most applications, as it performs
3756: a forward solve followed by a backward solve.
3758: The vectors b and x cannot be the same. I.e., one cannot
3759: call `MatBackwardSolve`(A,x,x).
3761: For matrix in `MATSEQBAIJ` format with block size larger than 1,
3762: the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3763: `MatForwardSolve()` solves U^T*D y = b, and
3764: `MatBackwardSolve()` solves U x = y.
3765: Thus they do not provide a symmetric preconditioner.
3767: Level: developer
3769: .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3770: @*/
3771: PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3772: {
3783: if (!mat->rmap->N && !mat->cmap->N) return 0;
3784: MatCheckPreallocated(mat, 1);
3786: PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0);
3787: PetscUseTypeMethod(mat, backwardsolve, b, x);
3788: PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0);
3789: PetscObjectStateIncrease((PetscObject)x);
3790: return 0;
3791: }
3793: /*@
3794: MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3796: Neighbor-wise Collective on mat
3798: Input Parameters:
3799: + mat - the factored matrix
3800: . b - the right-hand-side vector
3801: - y - the vector to be added to
3803: Output Parameter:
3804: . x - the result vector
3806: Note:
3807: The vectors b and x cannot be the same. I.e., one cannot
3808: call `MatSolveAdd`(A,x,y,x).
3810: Level: developer
3812: .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3813: @*/
3814: PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3815: {
3816: PetscScalar one = 1.0;
3817: Vec tmp;
3833: if (!mat->rmap->N && !mat->cmap->N) return 0;
3834: MatCheckPreallocated(mat, 1);
3836: PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y);
3837: if (mat->factorerrortype) {
3838: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3839: VecSetInf(x);
3840: } else if (mat->ops->solveadd) {
3841: PetscUseTypeMethod(mat, solveadd, b, y, x);
3842: } else {
3843: /* do the solve then the add manually */
3844: if (x != y) {
3845: MatSolve(mat, b, x);
3846: VecAXPY(x, one, y);
3847: } else {
3848: VecDuplicate(x, &tmp);
3849: VecCopy(x, tmp);
3850: MatSolve(mat, b, x);
3851: VecAXPY(x, one, tmp);
3852: VecDestroy(&tmp);
3853: }
3854: }
3855: PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y);
3856: PetscObjectStateIncrease((PetscObject)x);
3857: return 0;
3858: }
3860: /*@
3861: MatSolveTranspose - Solves A' x = b, given a factored matrix.
3863: Neighbor-wise Collective on mat
3865: Input Parameters:
3866: + mat - the factored matrix
3867: - b - the right-hand-side vector
3869: Output Parameter:
3870: . x - the result vector
3872: Notes:
3873: The vectors b and x cannot be the same. I.e., one cannot
3874: call `MatSolveTranspose`(A,x,x).
3876: Most users should employ the `KSP` interface for linear solvers
3877: instead of working directly with matrix algebra routines such as this.
3878: See, e.g., `KSPCreate()`.
3880: Level: developer
3882: .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3883: @*/
3884: PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3885: {
3886: PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3897: if (!mat->rmap->N && !mat->cmap->N) return 0;
3898: MatCheckPreallocated(mat, 1);
3899: PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0);
3900: if (mat->factorerrortype) {
3901: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3902: VecSetInf(x);
3903: } else {
3905: (*f)(mat, b, x);
3906: }
3907: PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0);
3908: PetscObjectStateIncrease((PetscObject)x);
3909: return 0;
3910: }
3912: /*@
3913: MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3914: factored matrix.
3916: Neighbor-wise Collective on mat
3918: Input Parameters:
3919: + mat - the factored matrix
3920: . b - the right-hand-side vector
3921: - y - the vector to be added to
3923: Output Parameter:
3924: . x - the result vector
3926: Note:
3927: The vectors b and x cannot be the same. I.e., one cannot
3928: call `MatSolveTransposeAdd`(A,x,y,x).
3930: Level: developer
3932: .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
3933: @*/
3934: PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
3935: {
3936: PetscScalar one = 1.0;
3937: Vec tmp;
3938: PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
3953: if (!mat->rmap->N && !mat->cmap->N) return 0;
3954: MatCheckPreallocated(mat, 1);
3956: PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y);
3957: if (mat->factorerrortype) {
3958: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3959: VecSetInf(x);
3960: } else if (f) {
3961: (*f)(mat, b, y, x);
3962: } else {
3963: /* do the solve then the add manually */
3964: if (x != y) {
3965: MatSolveTranspose(mat, b, x);
3966: VecAXPY(x, one, y);
3967: } else {
3968: VecDuplicate(x, &tmp);
3969: VecCopy(x, tmp);
3970: MatSolveTranspose(mat, b, x);
3971: VecAXPY(x, one, tmp);
3972: VecDestroy(&tmp);
3973: }
3974: }
3975: PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y);
3976: PetscObjectStateIncrease((PetscObject)x);
3977: return 0;
3978: }
3979: /* ----------------------------------------------------------------*/
3981: /*@
3982: MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
3984: Neighbor-wise Collective on mat
3986: Input Parameters:
3987: + mat - the matrix
3988: . b - the right hand side
3989: . omega - the relaxation factor
3990: . flag - flag indicating the type of SOR (see below)
3991: . shift - diagonal shift
3992: . its - the number of iterations
3993: - lits - the number of local iterations
3995: Output Parameter:
3996: . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
3998: SOR Flags:
3999: + `SOR_FORWARD_SWEEP` - forward SOR
4000: . `SOR_BACKWARD_SWEEP` - backward SOR
4001: . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4002: . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4003: . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4004: . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4005: . `SOR_EISENSTAT` - SOR with Eisenstat trick
4006: . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4007: upper/lower triangular part of matrix to
4008: vector (with omega)
4009: - `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4011: Notes:
4012: `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4013: `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4014: on each processor.
4016: Application programmers will not generally use `MatSOR()` directly,
4017: but instead will employ the `KSP`/`PC` interface.
4019: For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4021: Most users should employ the `KSP` interface for linear solvers
4022: instead of working directly with matrix algebra routines such as this.
4023: See, e.g., `KSPCreate()`.
4025: Vectors x and b CANNOT be the same
4027: Notes for Advanced Users:
4028: The flags are implemented as bitwise inclusive or operations.
4029: For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4030: to specify a zero initial guess for SSOR.
4032: Developer Note:
4033: We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4035: Level: developer
4037: .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4038: @*/
4039: PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4040: {
4056: MatCheckPreallocated(mat, 1);
4057: PetscLogEventBegin(MAT_SOR, mat, b, x, 0);
4058: PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4059: PetscLogEventEnd(MAT_SOR, mat, b, x, 0);
4060: PetscObjectStateIncrease((PetscObject)x);
4061: return 0;
4062: }
4064: /*
4065: Default matrix copy routine.
4066: */
4067: PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4068: {
4069: PetscInt i, rstart = 0, rend = 0, nz;
4070: const PetscInt *cwork;
4071: const PetscScalar *vwork;
4073: if (B->assembled) MatZeroEntries(B);
4074: if (str == SAME_NONZERO_PATTERN) {
4075: MatGetOwnershipRange(A, &rstart, &rend);
4076: for (i = rstart; i < rend; i++) {
4077: MatGetRow(A, i, &nz, &cwork, &vwork);
4078: MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES);
4079: MatRestoreRow(A, i, &nz, &cwork, &vwork);
4080: }
4081: } else {
4082: MatAYPX(B, 0.0, A, str);
4083: }
4084: MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);
4085: MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);
4086: return 0;
4087: }
4089: /*@
4090: MatCopy - Copies a matrix to another matrix.
4092: Collective on A
4094: Input Parameters:
4095: + A - the matrix
4096: - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4098: Output Parameter:
4099: . B - where the copy is put
4101: Notes:
4102: If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4104: `MatCopy()` copies the matrix entries of a matrix to another existing
4105: matrix (after first zeroing the second matrix). A related routine is
4106: `MatConvert()`, which first creates a new matrix and then copies the data.
4108: Level: intermediate
4110: .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4111: @*/
4112: PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4113: {
4114: PetscInt i;
4121: MatCheckPreallocated(B, 2);
4125: A->cmap->N, B->cmap->N);
4126: MatCheckPreallocated(A, 1);
4127: if (A == B) return 0;
4129: PetscLogEventBegin(MAT_Copy, A, B, 0, 0);
4130: if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4131: else MatCopy_Basic(A, B, str);
4133: B->stencil.dim = A->stencil.dim;
4134: B->stencil.noc = A->stencil.noc;
4135: for (i = 0; i <= A->stencil.dim; i++) {
4136: B->stencil.dims[i] = A->stencil.dims[i];
4137: B->stencil.starts[i] = A->stencil.starts[i];
4138: }
4140: PetscLogEventEnd(MAT_Copy, A, B, 0, 0);
4141: PetscObjectStateIncrease((PetscObject)B);
4142: return 0;
4143: }
4145: /*@C
4146: MatConvert - Converts a matrix to another matrix, either of the same
4147: or different type.
4149: Collective on mat
4151: Input Parameters:
4152: + mat - the matrix
4153: . newtype - new matrix type. Use `MATSAME` to create a new matrix of the
4154: same type as the original matrix.
4155: - reuse - denotes if the destination matrix is to be created or reused.
4156: 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
4157: `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).
4159: Output Parameter:
4160: . M - pointer to place new matrix
4162: Notes:
4163: `MatConvert()` first creates a new matrix and then copies the data from
4164: the first matrix. A related routine is `MatCopy()`, which copies the matrix
4165: entries of one matrix to another already existing matrix context.
4167: Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4168: the MPI communicator of the generated matrix is always the same as the communicator
4169: of the input matrix.
4171: Level: intermediate
4173: .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4174: @*/
4175: PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4176: {
4177: PetscBool sametype, issame, flg;
4178: PetscBool3 issymmetric, ishermitian;
4179: char convname[256], mtype[256];
4180: Mat B;
4187: MatCheckPreallocated(mat, 1);
4189: PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg);
4190: if (flg) newtype = mtype;
4192: PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype);
4193: PetscStrcmp(newtype, "same", &issame);
4197: if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4198: PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4199: return 0;
4200: }
4202: /* Cache Mat options because some converters use MatHeaderReplace */
4203: issymmetric = mat->symmetric;
4204: ishermitian = mat->hermitian;
4206: if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4207: PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4208: PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4209: } else {
4210: PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4211: const char *prefix[3] = {"seq", "mpi", ""};
4212: PetscInt i;
4213: /*
4214: Order of precedence:
4215: 0) See if newtype is a superclass of the current matrix.
4216: 1) See if a specialized converter is known to the current matrix.
4217: 2) See if a specialized converter is known to the desired matrix class.
4218: 3) See if a good general converter is registered for the desired class
4219: (as of 6/27/03 only MATMPIADJ falls into this category).
4220: 4) See if a good general converter is known for the current matrix.
4221: 5) Use a really basic converter.
4222: */
4224: /* 0) See if newtype is a superclass of the current matrix.
4225: i.e mat is mpiaij and newtype is aij */
4226: for (i = 0; i < 2; i++) {
4227: PetscStrncpy(convname, prefix[i], sizeof(convname));
4228: PetscStrlcat(convname, newtype, sizeof(convname));
4229: PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg);
4230: PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg);
4231: if (flg) {
4232: if (reuse == MAT_INPLACE_MATRIX) {
4233: PetscInfo(mat, "Early return\n");
4234: return 0;
4235: } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4236: PetscInfo(mat, "Calling MatDuplicate\n");
4237: PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4238: return 0;
4239: } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4240: PetscInfo(mat, "Calling MatCopy\n");
4241: MatCopy(mat, *M, SAME_NONZERO_PATTERN);
4242: return 0;
4243: }
4244: }
4245: }
4246: /* 1) See if a specialized converter is known to the current matrix and the desired class */
4247: for (i = 0; i < 3; i++) {
4248: PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4249: PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4250: PetscStrlcat(convname, "_", sizeof(convname));
4251: PetscStrlcat(convname, prefix[i], sizeof(convname));
4252: PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname));
4253: PetscStrlcat(convname, "_C", sizeof(convname));
4254: PetscObjectQueryFunction((PetscObject)mat, convname, &conv);
4255: PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv);
4256: if (conv) goto foundconv;
4257: }
4259: /* 2) See if a specialized converter is known to the desired matrix class. */
4260: MatCreate(PetscObjectComm((PetscObject)mat), &B);
4261: MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
4262: MatSetType(B, newtype);
4263: for (i = 0; i < 3; i++) {
4264: PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4265: PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4266: PetscStrlcat(convname, "_", sizeof(convname));
4267: PetscStrlcat(convname, prefix[i], sizeof(convname));
4268: PetscStrlcat(convname, newtype, sizeof(convname));
4269: PetscStrlcat(convname, "_C", sizeof(convname));
4270: PetscObjectQueryFunction((PetscObject)B, convname, &conv);
4271: PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv);
4272: if (conv) {
4273: MatDestroy(&B);
4274: goto foundconv;
4275: }
4276: }
4278: /* 3) See if a good general converter is registered for the desired class */
4279: conv = B->ops->convertfrom;
4280: PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv);
4281: MatDestroy(&B);
4282: if (conv) goto foundconv;
4284: /* 4) See if a good general converter is known for the current matrix */
4285: if (mat->ops->convert) conv = mat->ops->convert;
4286: PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv);
4287: if (conv) goto foundconv;
4289: /* 5) Use a really basic converter. */
4290: PetscInfo(mat, "Using MatConvert_Basic\n");
4291: conv = MatConvert_Basic;
4293: foundconv:
4294: PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4295: (*conv)(mat, newtype, reuse, M);
4296: if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4297: /* the block sizes must be same if the mappings are copied over */
4298: (*M)->rmap->bs = mat->rmap->bs;
4299: (*M)->cmap->bs = mat->cmap->bs;
4300: PetscObjectReference((PetscObject)mat->rmap->mapping);
4301: PetscObjectReference((PetscObject)mat->cmap->mapping);
4302: (*M)->rmap->mapping = mat->rmap->mapping;
4303: (*M)->cmap->mapping = mat->cmap->mapping;
4304: }
4305: (*M)->stencil.dim = mat->stencil.dim;
4306: (*M)->stencil.noc = mat->stencil.noc;
4307: for (i = 0; i <= mat->stencil.dim; i++) {
4308: (*M)->stencil.dims[i] = mat->stencil.dims[i];
4309: (*M)->stencil.starts[i] = mat->stencil.starts[i];
4310: }
4311: PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4312: }
4313: PetscObjectStateIncrease((PetscObject)*M);
4315: /* Copy Mat options */
4316: if (issymmetric == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE);
4317: else if (issymmetric == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE);
4318: if (ishermitian == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE);
4319: else if (ishermitian == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE);
4320: return 0;
4321: }
4323: /*@C
4324: MatFactorGetSolverType - Returns name of the package providing the factorization routines
4326: Not Collective
4328: Input Parameter:
4329: . mat - the matrix, must be a factored matrix
4331: Output Parameter:
4332: . type - the string name of the package (do not free this string)
4334: Note:
4335: In Fortran you pass in a empty string and the package name will be copied into it.
4336: (Make sure the string is long enough)
4338: Level: intermediate
4340: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4341: @*/
4342: PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4343: {
4344: PetscErrorCode (*conv)(Mat, MatSolverType *);
4350: PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv);
4351: if (conv) (*conv)(mat, type);
4352: else *type = MATSOLVERPETSC;
4353: return 0;
4354: }
4356: typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4357: struct _MatSolverTypeForSpecifcType {
4358: MatType mtype;
4359: /* no entry for MAT_FACTOR_NONE */
4360: PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4361: MatSolverTypeForSpecifcType next;
4362: };
4364: typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4365: struct _MatSolverTypeHolder {
4366: char *name;
4367: MatSolverTypeForSpecifcType handlers;
4368: MatSolverTypeHolder next;
4369: };
4371: static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4373: /*@C
4374: MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4376: Input Parameters:
4377: + package - name of the package, for example petsc or superlu
4378: . mtype - the matrix type that works with this package
4379: . ftype - the type of factorization supported by the package
4380: - createfactor - routine that will create the factored matrix ready to be used
4382: Level: developer
4384: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4385: @*/
4386: PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4387: {
4388: MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL;
4389: PetscBool flg;
4390: MatSolverTypeForSpecifcType inext, iprev = NULL;
4392: MatInitializePackage();
4393: if (!next) {
4394: PetscNew(&MatSolverTypeHolders);
4395: PetscStrallocpy(package, &MatSolverTypeHolders->name);
4396: PetscNew(&MatSolverTypeHolders->handlers);
4397: PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype);
4398: MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4399: return 0;
4400: }
4401: while (next) {
4402: PetscStrcasecmp(package, next->name, &flg);
4403: if (flg) {
4405: inext = next->handlers;
4406: while (inext) {
4407: PetscStrcasecmp(mtype, inext->mtype, &flg);
4408: if (flg) {
4409: inext->createfactor[(int)ftype - 1] = createfactor;
4410: return 0;
4411: }
4412: iprev = inext;
4413: inext = inext->next;
4414: }
4415: PetscNew(&iprev->next);
4416: PetscStrallocpy(mtype, (char **)&iprev->next->mtype);
4417: iprev->next->createfactor[(int)ftype - 1] = createfactor;
4418: return 0;
4419: }
4420: prev = next;
4421: next = next->next;
4422: }
4423: PetscNew(&prev->next);
4424: PetscStrallocpy(package, &prev->next->name);
4425: PetscNew(&prev->next->handlers);
4426: PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype);
4427: prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4428: return 0;
4429: }
4431: /*@C
4432: MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4434: Input Parameters:
4435: + type - name of the package, for example petsc or superlu
4436: . ftype - the type of factorization supported by the type
4437: - mtype - the matrix type that works with this type
4439: Output Parameters:
4440: + foundtype - `PETSC_TRUE` if the type was registered
4441: . foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4442: - createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4444: Level: developer
4446: .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4447: @*/
4448: PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4449: {
4450: MatSolverTypeHolder next = MatSolverTypeHolders;
4451: PetscBool flg;
4452: MatSolverTypeForSpecifcType inext;
4454: if (foundtype) *foundtype = PETSC_FALSE;
4455: if (foundmtype) *foundmtype = PETSC_FALSE;
4456: if (createfactor) *createfactor = NULL;
4458: if (type) {
4459: while (next) {
4460: PetscStrcasecmp(type, next->name, &flg);
4461: if (flg) {
4462: if (foundtype) *foundtype = PETSC_TRUE;
4463: inext = next->handlers;
4464: while (inext) {
4465: PetscStrbeginswith(mtype, inext->mtype, &flg);
4466: if (flg) {
4467: if (foundmtype) *foundmtype = PETSC_TRUE;
4468: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4469: return 0;
4470: }
4471: inext = inext->next;
4472: }
4473: }
4474: next = next->next;
4475: }
4476: } else {
4477: while (next) {
4478: inext = next->handlers;
4479: while (inext) {
4480: PetscStrcmp(mtype, inext->mtype, &flg);
4481: if (flg && inext->createfactor[(int)ftype - 1]) {
4482: if (foundtype) *foundtype = PETSC_TRUE;
4483: if (foundmtype) *foundmtype = PETSC_TRUE;
4484: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4485: return 0;
4486: }
4487: inext = inext->next;
4488: }
4489: next = next->next;
4490: }
4491: /* try with base classes inext->mtype */
4492: next = MatSolverTypeHolders;
4493: while (next) {
4494: inext = next->handlers;
4495: while (inext) {
4496: PetscStrbeginswith(mtype, inext->mtype, &flg);
4497: if (flg && inext->createfactor[(int)ftype - 1]) {
4498: if (foundtype) *foundtype = PETSC_TRUE;
4499: if (foundmtype) *foundmtype = PETSC_TRUE;
4500: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4501: return 0;
4502: }
4503: inext = inext->next;
4504: }
4505: next = next->next;
4506: }
4507: }
4508: return 0;
4509: }
4511: PetscErrorCode MatSolverTypeDestroy(void)
4512: {
4513: MatSolverTypeHolder next = MatSolverTypeHolders, prev;
4514: MatSolverTypeForSpecifcType inext, iprev;
4516: while (next) {
4517: PetscFree(next->name);
4518: inext = next->handlers;
4519: while (inext) {
4520: PetscFree(inext->mtype);
4521: iprev = inext;
4522: inext = inext->next;
4523: PetscFree(iprev);
4524: }
4525: prev = next;
4526: next = next->next;
4527: PetscFree(prev);
4528: }
4529: MatSolverTypeHolders = NULL;
4530: return 0;
4531: }
4533: /*@C
4534: MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4536: Logically Collective on mat
4538: Input Parameters:
4539: . mat - the matrix
4541: Output Parameters:
4542: . flg - `PETSC_TRUE` if uses the ordering
4544: Note:
4545: Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4546: packages do not, thus we want to skip generating the ordering when it is not needed or used.
4548: Level: developer
4550: .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4551: @*/
4552: PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4553: {
4554: *flg = mat->canuseordering;
4555: return 0;
4556: }
4558: /*@C
4559: MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4561: Logically Collective on mat
4563: Input Parameters:
4564: . mat - the matrix obtained with `MatGetFactor()`
4566: Output Parameters:
4567: . otype - the preferred type
4569: Level: developer
4571: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4572: @*/
4573: PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4574: {
4575: *otype = mat->preferredordering[ftype];
4577: return 0;
4578: }
4580: /*@C
4581: MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4583: Collective on mat
4585: Input Parameters:
4586: + mat - the matrix
4587: . type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4588: - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4590: Output Parameters:
4591: . f - the factor matrix used with MatXXFactorSymbolic() calls
4593: Options Database Key:
4594: . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4595: One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4597: Notes:
4598: Users usually access the factorization solvers via `KSP`
4600: Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4601: such as pastix, superlu, mumps etc.
4603: PETSc must have been ./configure to use the external solver, using the option --download-package
4605: Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4606: where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4607: call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix.
4609: Developer Note:
4610: This should actually be called `MatCreateFactor()` since it creates a new factor object
4612: Level: intermediate
4614: .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4615: `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4616: @*/
4617: PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4618: {
4619: PetscBool foundtype, foundmtype;
4620: PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4626: MatCheckPreallocated(mat, 1);
4628: MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv);
4629: if (!foundtype) {
4630: if (type) {
4631: 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],
4632: ((PetscObject)mat)->type_name, type);
4633: } else {
4634: 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);
4635: }
4636: }
4640: (*conv)(mat, ftype, f);
4641: if (mat->factorprefix) MatSetOptionsPrefix(*f, mat->factorprefix);
4642: return 0;
4643: }
4645: /*@C
4646: MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4648: Not Collective
4650: Input Parameters:
4651: + mat - the matrix
4652: . type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4653: - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4655: Output Parameter:
4656: . flg - PETSC_TRUE if the factorization is available
4658: Notes:
4659: Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4660: such as pastix, superlu, mumps etc.
4662: PETSc must have been ./configure to use the external solver, using the option --download-package
4664: Developer Note:
4665: This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4667: Level: intermediate
4669: .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4670: `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4671: @*/
4672: PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4673: {
4674: PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4681: MatCheckPreallocated(mat, 1);
4683: MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv);
4684: *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4685: return 0;
4686: }
4688: /*@
4689: MatDuplicate - Duplicates a matrix including the non-zero structure.
4691: Collective on mat
4693: Input Parameters:
4694: + mat - the matrix
4695: - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4696: See the manual page for `MatDuplicateOption()` for an explanation of these options.
4698: Output Parameter:
4699: . M - pointer to place new matrix
4701: Level: intermediate
4703: Notes:
4704: You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4706: 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.
4708: 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
4709: is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4710: User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4712: .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4713: @*/
4714: PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4715: {
4716: Mat B;
4717: VecType vtype;
4718: PetscInt i;
4719: PetscObject dm;
4720: void (*viewf)(void);
4727: MatCheckPreallocated(mat, 1);
4729: *M = NULL;
4730: PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4731: PetscUseTypeMethod(mat, duplicate, op, M);
4732: PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4733: B = *M;
4735: MatGetOperation(mat, MATOP_VIEW, &viewf);
4736: if (viewf) MatSetOperation(B, MATOP_VIEW, viewf);
4737: MatGetVecType(mat, &vtype);
4738: MatSetVecType(B, vtype);
4740: B->stencil.dim = mat->stencil.dim;
4741: B->stencil.noc = mat->stencil.noc;
4742: for (i = 0; i <= mat->stencil.dim; i++) {
4743: B->stencil.dims[i] = mat->stencil.dims[i];
4744: B->stencil.starts[i] = mat->stencil.starts[i];
4745: }
4747: B->nooffproczerorows = mat->nooffproczerorows;
4748: B->nooffprocentries = mat->nooffprocentries;
4750: PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm);
4751: if (dm) PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm);
4752: PetscObjectStateIncrease((PetscObject)B);
4753: return 0;
4754: }
4756: /*@
4757: MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4759: Logically Collective on mat
4761: Input Parameters:
4762: + mat - the matrix
4763: - v - the vector for storing the diagonal
4765: Output Parameter:
4766: . v - the diagonal of the matrix
4768: Level: intermediate
4770: Note:
4771: Currently only correct in parallel for square matrices.
4773: .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4774: @*/
4775: PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4776: {
4781: MatCheckPreallocated(mat, 1);
4783: PetscUseTypeMethod(mat, getdiagonal, v);
4784: PetscObjectStateIncrease((PetscObject)v);
4785: return 0;
4786: }
4788: /*@C
4789: MatGetRowMin - Gets the minimum value (of the real part) of each
4790: row of the matrix
4792: Logically Collective on mat
4794: Input Parameter:
4795: . mat - the matrix
4797: Output Parameters:
4798: + v - the vector for storing the maximums
4799: - idx - the indices of the column found for each row (optional)
4801: Level: intermediate
4803: Note:
4804: The result of this call are the same as if one converted the matrix to dense format
4805: and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4807: This code is only implemented for a couple of matrix formats.
4809: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4810: `MatGetRowMax()`
4811: @*/
4812: PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4813: {
4819: if (!mat->cmap->N) {
4820: VecSet(v, PETSC_MAX_REAL);
4821: if (idx) {
4822: PetscInt i, m = mat->rmap->n;
4823: for (i = 0; i < m; i++) idx[i] = -1;
4824: }
4825: } else {
4826: MatCheckPreallocated(mat, 1);
4827: }
4828: PetscUseTypeMethod(mat, getrowmin, v, idx);
4829: PetscObjectStateIncrease((PetscObject)v);
4830: return 0;
4831: }
4833: /*@C
4834: MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4835: row of the matrix
4837: Logically Collective on mat
4839: Input Parameter:
4840: . mat - the matrix
4842: Output Parameters:
4843: + v - the vector for storing the minimums
4844: - idx - the indices of the column found for each row (or NULL if not needed)
4846: Level: intermediate
4848: Notes:
4849: if a row is completely empty or has only 0.0 values then the idx[] value for that
4850: row is 0 (the first column).
4852: This code is only implemented for a couple of matrix formats.
4854: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4855: @*/
4856: PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4857: {
4864: if (!mat->cmap->N) {
4865: VecSet(v, 0.0);
4866: if (idx) {
4867: PetscInt i, m = mat->rmap->n;
4868: for (i = 0; i < m; i++) idx[i] = -1;
4869: }
4870: } else {
4871: MatCheckPreallocated(mat, 1);
4872: if (idx) PetscArrayzero(idx, mat->rmap->n);
4873: PetscUseTypeMethod(mat, getrowminabs, v, idx);
4874: }
4875: PetscObjectStateIncrease((PetscObject)v);
4876: return 0;
4877: }
4879: /*@C
4880: MatGetRowMax - Gets the maximum value (of the real part) of each
4881: row of the matrix
4883: Logically Collective on mat
4885: Input Parameter:
4886: . mat - the matrix
4888: Output Parameters:
4889: + v - the vector for storing the maximums
4890: - idx - the indices of the column found for each row (optional)
4892: Level: intermediate
4894: Notes:
4895: The result of this call are the same as if one converted the matrix to dense format
4896: and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4898: This code is only implemented for a couple of matrix formats.
4900: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4901: @*/
4902: PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
4903: {
4909: if (!mat->cmap->N) {
4910: VecSet(v, PETSC_MIN_REAL);
4911: if (idx) {
4912: PetscInt i, m = mat->rmap->n;
4913: for (i = 0; i < m; i++) idx[i] = -1;
4914: }
4915: } else {
4916: MatCheckPreallocated(mat, 1);
4917: PetscUseTypeMethod(mat, getrowmax, v, idx);
4918: }
4919: PetscObjectStateIncrease((PetscObject)v);
4920: return 0;
4921: }
4923: /*@C
4924: MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4925: row of the matrix
4927: Logically Collective on mat
4929: Input Parameter:
4930: . mat - the matrix
4932: Output Parameters:
4933: + v - the vector for storing the maximums
4934: - idx - the indices of the column found for each row (or NULL if not needed)
4936: Level: intermediate
4938: Notes:
4939: if a row is completely empty or has only 0.0 values then the idx[] value for that
4940: row is 0 (the first column).
4942: This code is only implemented for a couple of matrix formats.
4944: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4945: @*/
4946: PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
4947: {
4953: if (!mat->cmap->N) {
4954: VecSet(v, 0.0);
4955: if (idx) {
4956: PetscInt i, m = mat->rmap->n;
4957: for (i = 0; i < m; i++) idx[i] = -1;
4958: }
4959: } else {
4960: MatCheckPreallocated(mat, 1);
4961: if (idx) PetscArrayzero(idx, mat->rmap->n);
4962: PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
4963: }
4964: PetscObjectStateIncrease((PetscObject)v);
4965: return 0;
4966: }
4968: /*@
4969: MatGetRowSum - Gets the sum of each row of the matrix
4971: Logically or Neighborhood Collective on mat
4973: Input Parameters:
4974: . mat - the matrix
4976: Output Parameter:
4977: . v - the vector for storing the sum of rows
4979: Level: intermediate
4981: Notes:
4982: This code is slow since it is not currently specialized for different formats
4984: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
4985: @*/
4986: PetscErrorCode MatGetRowSum(Mat mat, Vec v)
4987: {
4988: Vec ones;
4994: MatCheckPreallocated(mat, 1);
4995: MatCreateVecs(mat, &ones, NULL);
4996: VecSet(ones, 1.);
4997: MatMult(mat, ones, v);
4998: VecDestroy(&ones);
4999: return 0;
5000: }
5002: /*@
5003: MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5004: when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5006: Collective on mat
5008: Input Parameter:
5009: . mat - the matrix to provide the transpose
5011: Output Parameter:
5012: . 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
5014: Level: advanced
5016: Note:
5017: 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
5018: routine allows bypassing that call.
5020: .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5021: @*/
5022: PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5023: {
5024: PetscContainer rB = NULL;
5025: MatParentState *rb = NULL;
5027: PetscNew(&rb);
5028: rb->id = ((PetscObject)mat)->id;
5029: rb->state = 0;
5030: MatGetNonzeroState(mat, &rb->nonzerostate);
5031: PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB);
5032: PetscContainerSetPointer(rB, rb);
5033: PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault);
5034: PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB);
5035: PetscObjectDereference((PetscObject)rB);
5036: return 0;
5037: }
5039: /*@
5040: MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5042: Collective on mat
5044: Input Parameters:
5045: + mat - the matrix to transpose
5046: - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5048: Output Parameter:
5049: . B - the transpose
5051: Notes:
5052: If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5054: `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
5055: transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5057: 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.
5059: Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5061: If mat is unchanged from the last call this function returns immediately without recomputing the result
5063: If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5065: Level: intermediate
5067: .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5068: `MatTransposeSymbolic()`
5069: @*/
5070: PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5071: {
5072: PetscContainer rB = NULL;
5073: MatParentState *rb = NULL;
5081: MatCheckPreallocated(mat, 1);
5082: if (reuse == MAT_REUSE_MATRIX) {
5083: PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5085: PetscContainerGetPointer(rB, (void **)&rb);
5087: if (rb->state == ((PetscObject)mat)->state) return 0;
5088: }
5090: PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0);
5091: if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5092: PetscUseTypeMethod(mat, transpose, reuse, B);
5093: PetscObjectStateIncrease((PetscObject)*B);
5094: }
5095: PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0);
5097: if (reuse == MAT_INITIAL_MATRIX) MatTransposeSetPrecursor(mat, *B);
5098: if (reuse != MAT_INPLACE_MATRIX) {
5099: PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5100: PetscContainerGetPointer(rB, (void **)&rb);
5101: rb->state = ((PetscObject)mat)->state;
5102: rb->nonzerostate = mat->nonzerostate;
5103: }
5104: return 0;
5105: }
5107: /*@
5108: MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5110: Collective on A
5112: Input Parameters:
5113: . A - the matrix to transpose
5115: Output Parameter:
5116: . 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
5117: numerical portion.
5119: Level: intermediate
5121: Note:
5122: This is not supported for many matrix types, use `MatTranspose()` in those cases
5124: .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5125: @*/
5126: PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5127: {
5133: PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0);
5134: (*A->ops->transposesymbolic)(A, B);
5135: PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0);
5137: MatTransposeSetPrecursor(A, *B);
5138: return 0;
5139: }
5141: PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5142: {
5143: PetscContainer rB;
5144: MatParentState *rb;
5150: PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB);
5152: PetscContainerGetPointer(rB, (void **)&rb);
5155: return 0;
5156: }
5158: /*@
5159: MatIsTranspose - Test whether a matrix is another one's transpose,
5160: or its own, in which case it tests symmetry.
5162: Collective on A
5164: Input Parameters:
5165: + A - the matrix to test
5166: - B - the matrix to test against, this can equal the first parameter
5168: Output Parameters:
5169: . flg - the result
5171: Notes:
5172: Only available for `MATAIJ` matrices.
5174: The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5175: test involves parallel copies of the block-offdiagonal parts of the matrix.
5177: Level: intermediate
5179: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5180: @*/
5181: PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5182: {
5183: PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5188: PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f);
5189: PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g);
5190: *flg = PETSC_FALSE;
5191: if (f && g) {
5193: (*f)(A, B, tol, flg);
5194: } else {
5195: MatType mattype;
5197: MatGetType(f ? B : A, &mattype);
5198: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5199: }
5200: return 0;
5201: }
5203: /*@
5204: MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5206: Collective on mat
5208: Input Parameters:
5209: + mat - the matrix to transpose and complex conjugate
5210: - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5212: Output Parameter:
5213: . B - the Hermitian transpose
5215: Level: intermediate
5217: .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5218: @*/
5219: PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5220: {
5221: MatTranspose(mat, reuse, B);
5222: #if defined(PETSC_USE_COMPLEX)
5223: MatConjugate(*B);
5224: #endif
5225: return 0;
5226: }
5228: /*@
5229: MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5231: Collective on A
5233: Input Parameters:
5234: + A - the matrix to test
5235: - B - the matrix to test against, this can equal the first parameter
5237: Output Parameters:
5238: . flg - the result
5240: Notes:
5241: Only available for `MATAIJ` matrices.
5243: The sequential algorithm
5244: has a running time of the order of the number of nonzeros; the parallel
5245: test involves parallel copies of the block-offdiagonal parts of the matrix.
5247: Level: intermediate
5249: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5250: @*/
5251: PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5252: {
5253: PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5258: PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f);
5259: PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g);
5260: if (f && g) {
5262: (*f)(A, B, tol, flg);
5263: }
5264: return 0;
5265: }
5267: /*@
5268: MatPermute - Creates a new matrix with rows and columns permuted from the
5269: original.
5271: Collective on mat
5273: Input Parameters:
5274: + mat - the matrix to permute
5275: . row - row permutation, each processor supplies only the permutation for its rows
5276: - col - column permutation, each processor supplies only the permutation for its columns
5278: Output Parameters:
5279: . B - the permuted matrix
5281: Level: advanced
5283: Note:
5284: The index sets map from row/col of permuted matrix to row/col of original matrix.
5285: The index sets should be on the same communicator as mat and have the same local sizes.
5287: Developer Note:
5288: If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5289: exploit the fact that row and col are permutations, consider implementing the
5290: more general `MatCreateSubMatrix()` instead.
5292: .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5293: @*/
5294: PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5295: {
5306: MatCheckPreallocated(mat, 1);
5308: if (mat->ops->permute) {
5309: PetscUseTypeMethod(mat, permute, row, col, B);
5310: PetscObjectStateIncrease((PetscObject)*B);
5311: } else {
5312: MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B);
5313: }
5314: return 0;
5315: }
5317: /*@
5318: MatEqual - Compares two matrices.
5320: Collective on A
5322: Input Parameters:
5323: + A - the first matrix
5324: - B - the second matrix
5326: Output Parameter:
5327: . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5329: Level: intermediate
5331: .seealso: `Mat`
5332: @*/
5333: PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5334: {
5341: MatCheckPreallocated(A, 1);
5342: MatCheckPreallocated(B, 2);
5346: B->cmap->N);
5347: if (A->ops->equal && A->ops->equal == B->ops->equal) {
5348: PetscUseTypeMethod(A, equal, B, flg);
5349: } else {
5350: MatMultEqual(A, B, 10, flg);
5351: }
5352: return 0;
5353: }
5355: /*@
5356: MatDiagonalScale - Scales a matrix on the left and right by diagonal
5357: matrices that are stored as vectors. Either of the two scaling
5358: matrices can be NULL.
5360: Collective on mat
5362: Input Parameters:
5363: + mat - the matrix to be scaled
5364: . l - the left scaling vector (or NULL)
5365: - r - the right scaling vector (or NULL)
5367: Note:
5368: `MatDiagonalScale()` computes A = LAR, where
5369: L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5370: The L scales the rows of the matrix, the R scales the columns of the matrix.
5372: Level: intermediate
5374: .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5375: @*/
5376: PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5377: {
5380: if (l) {
5383: }
5384: if (r) {
5387: }
5390: MatCheckPreallocated(mat, 1);
5391: if (!l && !r) return 0;
5393: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5394: PetscUseTypeMethod(mat, diagonalscale, l, r);
5395: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5396: PetscObjectStateIncrease((PetscObject)mat);
5397: if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5398: return 0;
5399: }
5401: /*@
5402: MatScale - Scales all elements of a matrix by a given number.
5404: Logically Collective on mat
5406: Input Parameters:
5407: + mat - the matrix to be scaled
5408: - a - the scaling value
5410: Output Parameter:
5411: . mat - the scaled matrix
5413: Level: intermediate
5415: .seealso: `Mat`, `MatDiagonalScale()`
5416: @*/
5417: PetscErrorCode MatScale(Mat mat, PetscScalar a)
5418: {
5425: MatCheckPreallocated(mat, 1);
5427: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5428: if (a != (PetscScalar)1.0) {
5429: PetscUseTypeMethod(mat, scale, a);
5430: PetscObjectStateIncrease((PetscObject)mat);
5431: }
5432: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5433: return 0;
5434: }
5436: /*@
5437: MatNorm - Calculates various norms of a matrix.
5439: Collective on mat
5441: Input Parameters:
5442: + mat - the matrix
5443: - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5445: Output Parameter:
5446: . nrm - the resulting norm
5448: Level: intermediate
5450: .seealso: `Mat`
5451: @*/
5452: PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5453: {
5460: MatCheckPreallocated(mat, 1);
5462: PetscUseTypeMethod(mat, norm, type, nrm);
5463: return 0;
5464: }
5466: /*
5467: This variable is used to prevent counting of MatAssemblyBegin() that
5468: are called from within a MatAssemblyEnd().
5469: */
5470: static PetscInt MatAssemblyEnd_InUse = 0;
5471: /*@
5472: MatAssemblyBegin - Begins assembling the matrix. This routine should
5473: be called after completing all calls to `MatSetValues()`.
5475: Collective on mat
5477: Input Parameters:
5478: + mat - the matrix
5479: - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5481: Notes:
5482: `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to
5483: use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5485: Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5486: in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5487: using the matrix.
5489: ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5490: 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
5491: a global collective operation requring all processes that share the matrix.
5493: Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5494: out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5495: before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5497: Level: beginner
5499: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5500: @*/
5501: PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5502: {
5505: MatCheckPreallocated(mat, 1);
5507: if (mat->assembled) {
5508: mat->was_assembled = PETSC_TRUE;
5509: mat->assembled = PETSC_FALSE;
5510: }
5512: if (!MatAssemblyEnd_InUse) {
5513: PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0);
5514: PetscTryTypeMethod(mat, assemblybegin, type);
5515: PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0);
5516: } else PetscTryTypeMethod(mat, assemblybegin, type);
5517: return 0;
5518: }
5520: /*@
5521: MatAssembled - Indicates if a matrix has been assembled and is ready for
5522: use; for example, in matrix-vector product.
5524: Not Collective
5526: Input Parameter:
5527: . mat - the matrix
5529: Output Parameter:
5530: . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5532: Level: advanced
5534: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5535: @*/
5536: PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5537: {
5540: *assembled = mat->assembled;
5541: return 0;
5542: }
5544: /*@
5545: MatAssemblyEnd - Completes assembling the matrix. This routine should
5546: be called after `MatAssemblyBegin()`.
5548: Collective on Mat
5550: Input Parameters:
5551: + mat - the matrix
5552: - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5554: Options Database Keys:
5555: + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5556: . -mat_view ::ascii_info_detail - Prints more detailed info
5557: . -mat_view - Prints matrix in ASCII format
5558: . -mat_view ::ascii_matlab - Prints matrix in Matlab format
5559: . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5560: . -display <name> - Sets display name (default is host)
5561: . -draw_pause <sec> - Sets number of seconds to pause after display
5562: . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5563: . -viewer_socket_machine <machine> - Machine to use for socket
5564: . -viewer_socket_port <port> - Port number to use for socket
5565: - -mat_view binary:filename[:append] - Save matrix to file in binary format
5567: Level: beginner
5569: .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5570: @*/
5571: PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5572: {
5573: static PetscInt inassm = 0;
5574: PetscBool flg = PETSC_FALSE;
5579: inassm++;
5580: MatAssemblyEnd_InUse++;
5581: if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5582: PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0);
5583: PetscTryTypeMethod(mat, assemblyend, type);
5584: PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0);
5585: } else PetscTryTypeMethod(mat, assemblyend, type);
5587: /* Flush assembly is not a true assembly */
5588: if (type != MAT_FLUSH_ASSEMBLY) {
5589: if (mat->num_ass) {
5590: if (!mat->symmetry_eternal) {
5591: mat->symmetric = PETSC_BOOL3_UNKNOWN;
5592: mat->hermitian = PETSC_BOOL3_UNKNOWN;
5593: }
5594: if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5595: if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5596: }
5597: mat->num_ass++;
5598: mat->assembled = PETSC_TRUE;
5599: mat->ass_nonzerostate = mat->nonzerostate;
5600: }
5602: mat->insertmode = NOT_SET_VALUES;
5603: MatAssemblyEnd_InUse--;
5604: PetscObjectStateIncrease((PetscObject)mat);
5605: if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5606: MatViewFromOptions(mat, NULL, "-mat_view");
5608: if (mat->checksymmetryonassembly) {
5609: MatIsSymmetric(mat, mat->checksymmetrytol, &flg);
5610: if (flg) {
5611: PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5612: } else {
5613: PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5614: }
5615: }
5616: if (mat->nullsp && mat->checknullspaceonassembly) MatNullSpaceTest(mat->nullsp, mat, NULL);
5617: }
5618: inassm--;
5619: return 0;
5620: }
5622: /*@
5623: MatSetOption - Sets a parameter option for a matrix. Some options
5624: may be specific to certain storage formats. Some options
5625: determine how values will be inserted (or added). Sorted,
5626: row-oriented input will generally assemble the fastest. The default
5627: is row-oriented.
5629: Logically Collective on mat for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5631: Input Parameters:
5632: + mat - the matrix
5633: . option - the option, one of those listed below (and possibly others),
5634: - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5636: Options Describing Matrix Structure:
5637: + `MAT_SPD` - symmetric positive definite
5638: . `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5639: . `MAT_HERMITIAN` - transpose is the complex conjugation
5640: . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5641: . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5642: . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5643: - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5645: These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5646: do not need to be computed (usually at a high cost)
5648: Options For Use with `MatSetValues()`:
5649: Insert a logically dense subblock, which can be
5650: . `MAT_ROW_ORIENTED` - row-oriented (default)
5652: Note these options reflect the data you pass in with `MatSetValues()`; it has
5653: nothing to do with how the data is stored internally in the matrix
5654: data structure.
5656: When (re)assembling a matrix, we can restrict the input for
5657: efficiency/debugging purposes. These options include
5658: + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5659: . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5660: . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5661: . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5662: . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5663: . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5664: any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5665: performance for very large process counts.
5666: - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5667: of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5668: functions, instead sending only neighbor messages.
5670: Notes:
5671: Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5673: Some options are relevant only for particular matrix types and
5674: are thus ignored by others. Other options are not supported by
5675: certain matrix types and will generate an error message if set.
5677: If using a Fortran 77 module to compute a matrix, one may need to
5678: use the column-oriented option (or convert to the row-oriented
5679: format).
5681: `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5682: that would generate a new entry in the nonzero structure is instead
5683: ignored. Thus, if memory has not alredy been allocated for this particular
5684: data, then the insertion is ignored. For dense matrices, in which
5685: the entire array is allocated, no entries are ever ignored.
5686: Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5688: `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5689: that would generate a new entry in the nonzero structure instead produces
5690: 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
5692: `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5693: that would generate a new entry that has not been preallocated will
5694: instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5695: only.) This is a useful flag when debugging matrix memory preallocation.
5696: If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5698: `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5699: other processors should be dropped, rather than stashed.
5700: This is useful if you know that the "owning" processor is also
5701: always generating the correct matrix entries, so that PETSc need
5702: not transfer duplicate entries generated on another processor.
5704: `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5705: searches during matrix assembly. When this flag is set, the hash table
5706: is created during the first matrix assembly. This hash table is
5707: used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5708: to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5709: should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5710: supported by` MATMPIBAIJ` format only.
5712: `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5713: are kept in the nonzero structure
5715: `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5716: a zero location in the matrix
5718: `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5720: `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5721: zero row routines and thus improves performance for very large process counts.
5723: `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5724: part of the matrix (since they should match the upper triangular part).
5726: `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5727: single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5728: with finite difference schemes with non-periodic boundary conditions.
5730: Developer Note:
5731: `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5732: places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5733: to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5734: not changed.
5736: Level: intermediate
5738: .seealso: `MatOption`, `Mat`, `MatGetOption()`
5739: @*/
5740: PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5741: {
5743: if (op > 0) {
5746: }
5750: switch (op) {
5751: case MAT_FORCE_DIAGONAL_ENTRIES:
5752: mat->force_diagonals = flg;
5753: return 0;
5754: case MAT_NO_OFF_PROC_ENTRIES:
5755: mat->nooffprocentries = flg;
5756: return 0;
5757: case MAT_SUBSET_OFF_PROC_ENTRIES:
5758: mat->assembly_subset = flg;
5759: if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5760: #if !defined(PETSC_HAVE_MPIUNI)
5761: MatStashScatterDestroy_BTS(&mat->stash);
5762: #endif
5763: mat->stash.first_assembly_done = PETSC_FALSE;
5764: }
5765: return 0;
5766: case MAT_NO_OFF_PROC_ZERO_ROWS:
5767: mat->nooffproczerorows = flg;
5768: return 0;
5769: case MAT_SPD:
5770: if (flg) {
5771: mat->spd = PETSC_BOOL3_TRUE;
5772: mat->symmetric = PETSC_BOOL3_TRUE;
5773: mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5774: } else {
5775: mat->spd = PETSC_BOOL3_FALSE;
5776: }
5777: break;
5778: case MAT_SYMMETRIC:
5779: mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5780: if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5781: #if !defined(PETSC_USE_COMPLEX)
5782: mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5783: #endif
5784: break;
5785: case MAT_HERMITIAN:
5786: mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5787: if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5788: #if !defined(PETSC_USE_COMPLEX)
5789: mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5790: #endif
5791: break;
5792: case MAT_STRUCTURALLY_SYMMETRIC:
5793: mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5794: break;
5795: case MAT_SYMMETRY_ETERNAL:
5797: mat->symmetry_eternal = flg;
5798: if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5799: break;
5800: case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5802: mat->structural_symmetry_eternal = flg;
5803: break;
5804: case MAT_SPD_ETERNAL:
5806: mat->spd_eternal = flg;
5807: if (flg) {
5808: mat->structural_symmetry_eternal = PETSC_TRUE;
5809: mat->symmetry_eternal = PETSC_TRUE;
5810: }
5811: break;
5812: case MAT_STRUCTURE_ONLY:
5813: mat->structure_only = flg;
5814: break;
5815: case MAT_SORTED_FULL:
5816: mat->sortedfull = flg;
5817: break;
5818: default:
5819: break;
5820: }
5821: PetscTryTypeMethod(mat, setoption, op, flg);
5822: return 0;
5823: }
5825: /*@
5826: MatGetOption - Gets a parameter option that has been set for a matrix.
5828: Logically Collective on mat
5830: Input Parameters:
5831: + mat - the matrix
5832: - option - the option, this only responds to certain options, check the code for which ones
5834: Output Parameter:
5835: . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5837: Notes:
5838: Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5840: Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5841: `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5843: Level: intermediate
5845: .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5846: `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5847: @*/
5848: PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5849: {
5856: switch (op) {
5857: case MAT_NO_OFF_PROC_ENTRIES:
5858: *flg = mat->nooffprocentries;
5859: break;
5860: case MAT_NO_OFF_PROC_ZERO_ROWS:
5861: *flg = mat->nooffproczerorows;
5862: break;
5863: case MAT_SYMMETRIC:
5864: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5865: break;
5866: case MAT_HERMITIAN:
5867: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5868: break;
5869: case MAT_STRUCTURALLY_SYMMETRIC:
5870: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5871: break;
5872: case MAT_SPD:
5873: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
5874: break;
5875: case MAT_SYMMETRY_ETERNAL:
5876: *flg = mat->symmetry_eternal;
5877: break;
5878: case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5879: *flg = mat->symmetry_eternal;
5880: break;
5881: default:
5882: break;
5883: }
5884: return 0;
5885: }
5887: /*@
5888: MatZeroEntries - Zeros all entries of a matrix. For sparse matrices
5889: this routine retains the old nonzero structure.
5891: Logically Collective on mat
5893: Input Parameters:
5894: . mat - the matrix
5896: Level: intermediate
5898: Note:
5899: 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.
5900: See the Performance chapter of the users manual for information on preallocating matrices.
5902: .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
5903: @*/
5904: PetscErrorCode MatZeroEntries(Mat mat)
5905: {
5910: MatCheckPreallocated(mat, 1);
5912: PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0);
5913: PetscUseTypeMethod(mat, zeroentries);
5914: PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0);
5915: PetscObjectStateIncrease((PetscObject)mat);
5916: return 0;
5917: }
5919: /*@
5920: MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5921: of a set of rows and columns of a matrix.
5923: Collective on mat
5925: Input Parameters:
5926: + mat - the matrix
5927: . numRows - the number of rows to remove
5928: . rows - the global row indices
5929: . diag - value put in the diagonal of the eliminated rows
5930: . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5931: - b - optional vector of right hand side, that will be adjusted by provided solution
5933: Notes:
5934: This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5936: For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5937: 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
5939: If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5940: Krylov method to take advantage of the known solution on the zeroed rows.
5942: For the parallel case, all processes that share the matrix (i.e.,
5943: those in the communicator used for matrix creation) MUST call this
5944: routine, regardless of whether any rows being zeroed are owned by
5945: them.
5947: Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5949: Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5950: list only rows local to itself).
5952: The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
5954: Level: intermediate
5956: .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5957: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5958: @*/
5959: PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
5960: {
5966: MatCheckPreallocated(mat, 1);
5968: PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
5969: MatViewFromOptions(mat, NULL, "-mat_view");
5970: PetscObjectStateIncrease((PetscObject)mat);
5971: return 0;
5972: }
5974: /*@
5975: MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5976: of a set of rows and columns of a matrix.
5978: Collective on mat
5980: Input Parameters:
5981: + mat - the matrix
5982: . is - the rows to zero
5983: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5984: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5985: - b - optional vector of right hand side, that will be adjusted by provided solution
5987: Note:
5988: See `MatZeroRowsColumns()` for details on how this routine operates.
5990: Level: intermediate
5992: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5993: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
5994: @*/
5995: PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
5996: {
5997: PetscInt numRows;
5998: const PetscInt *rows;
6004: ISGetLocalSize(is, &numRows);
6005: ISGetIndices(is, &rows);
6006: MatZeroRowsColumns(mat, numRows, rows, diag, x, b);
6007: ISRestoreIndices(is, &rows);
6008: return 0;
6009: }
6011: /*@
6012: MatZeroRows - Zeros all entries (except possibly the main diagonal)
6013: of a set of rows of a matrix.
6015: Collective on mat
6017: Input Parameters:
6018: + mat - the matrix
6019: . numRows - the number of rows to remove
6020: . rows - the global row indices
6021: . diag - value put in the diagonal of the eliminated rows
6022: . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6023: - b - optional vector of right hand side, that will be adjusted by provided solution
6025: Notes:
6026: This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6028: For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6030: If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6031: Krylov method to take advantage of the known solution on the zeroed rows.
6033: 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)
6034: from the matrix.
6036: Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6037: 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
6038: formats this does not alter the nonzero structure.
6040: If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6041: of the matrix is not changed the values are
6042: merely zeroed.
6044: The user can set a value in the diagonal entry (or for the `MATAIJ` format
6045: formats can optionally remove the main diagonal entry from the
6046: nonzero structure as well, by passing 0.0 as the final argument).
6048: For the parallel case, all processes that share the matrix (i.e.,
6049: those in the communicator used for matrix creation) MUST call this
6050: routine, regardless of whether any rows being zeroed are owned by
6051: them.
6053: Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6054: list only rows local to itself).
6056: You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6057: owns that are to be zeroed. This saves a global synchronization in the implementation.
6059: Level: intermediate
6061: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6062: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6063: @*/
6064: PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6065: {
6071: MatCheckPreallocated(mat, 1);
6073: PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6074: MatViewFromOptions(mat, NULL, "-mat_view");
6075: PetscObjectStateIncrease((PetscObject)mat);
6076: return 0;
6077: }
6079: /*@
6080: MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6081: of a set of rows of a matrix.
6083: Collective on Mat
6085: Input Parameters:
6086: + mat - the matrix
6087: . is - index set of rows to remove (if NULL then no row is removed)
6088: . diag - value put in all diagonals of eliminated rows
6089: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6090: - b - optional vector of right hand side, that will be adjusted by provided solution
6092: Note:
6093: See `MatZeroRows()` for details on how this routine operates.
6095: Level: intermediate
6097: .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6098: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6099: @*/
6100: PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6101: {
6102: PetscInt numRows = 0;
6103: const PetscInt *rows = NULL;
6107: if (is) {
6109: ISGetLocalSize(is, &numRows);
6110: ISGetIndices(is, &rows);
6111: }
6112: MatZeroRows(mat, numRows, rows, diag, x, b);
6113: if (is) ISRestoreIndices(is, &rows);
6114: return 0;
6115: }
6117: /*@
6118: MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6119: of a set of rows of a matrix. These rows must be local to the process.
6121: Collective on mat
6123: Input Parameters:
6124: + mat - the matrix
6125: . numRows - the number of rows to remove
6126: . rows - the grid coordinates (and component number when dof > 1) for matrix rows
6127: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6128: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6129: - b - optional vector of right hand side, that will be adjusted by provided solution
6131: Notes:
6132: See `MatZeroRows()` for details on how this routine operates.
6134: The grid coordinates are across the entire grid, not just the local portion
6136: In Fortran idxm and idxn should be declared as
6137: $ MatStencil idxm(4,m)
6138: and the values inserted using
6139: $ idxm(MatStencil_i,1) = i
6140: $ idxm(MatStencil_j,1) = j
6141: $ idxm(MatStencil_k,1) = k
6142: $ idxm(MatStencil_c,1) = c
6143: etc
6145: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6146: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6147: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6148: `DM_BOUNDARY_PERIODIC` boundary type.
6150: 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
6151: a single value per point) you can skip filling those indices.
6153: Level: intermediate
6155: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6156: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6157: @*/
6158: PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6159: {
6160: PetscInt dim = mat->stencil.dim;
6161: PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc);
6162: PetscInt *dims = mat->stencil.dims + 1;
6163: PetscInt *starts = mat->stencil.starts;
6164: PetscInt *dxm = (PetscInt *)rows;
6165: PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6171: PetscMalloc1(numRows, &jdxm);
6172: for (i = 0; i < numRows; ++i) {
6173: /* Skip unused dimensions (they are ordered k, j, i, c) */
6174: for (j = 0; j < 3 - sdim; ++j) dxm++;
6175: /* Local index in X dir */
6176: tmp = *dxm++ - starts[0];
6177: /* Loop over remaining dimensions */
6178: for (j = 0; j < dim - 1; ++j) {
6179: /* If nonlocal, set index to be negative */
6180: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6181: /* Update local index */
6182: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6183: }
6184: /* Skip component slot if necessary */
6185: if (mat->stencil.noc) dxm++;
6186: /* Local row number */
6187: if (tmp >= 0) jdxm[numNewRows++] = tmp;
6188: }
6189: MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b);
6190: PetscFree(jdxm);
6191: return 0;
6192: }
6194: /*@
6195: MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6196: of a set of rows and columns of a matrix.
6198: Collective on mat
6200: Input Parameters:
6201: + mat - the matrix
6202: . numRows - the number of rows/columns to remove
6203: . rows - the grid coordinates (and component number when dof > 1) for matrix rows
6204: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6205: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6206: - b - optional vector of right hand side, that will be adjusted by provided solution
6208: Notes:
6209: See `MatZeroRowsColumns()` for details on how this routine operates.
6211: The grid coordinates are across the entire grid, not just the local portion
6213: In Fortran idxm and idxn should be declared as
6214: $ MatStencil idxm(4,m)
6215: and the values inserted using
6216: $ idxm(MatStencil_i,1) = i
6217: $ idxm(MatStencil_j,1) = j
6218: $ idxm(MatStencil_k,1) = k
6219: $ idxm(MatStencil_c,1) = c
6220: etc
6222: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6223: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6224: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6225: `DM_BOUNDARY_PERIODIC` boundary type.
6227: 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
6228: a single value per point) you can skip filling those indices.
6230: Level: intermediate
6232: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6233: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6234: @*/
6235: PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6236: {
6237: PetscInt dim = mat->stencil.dim;
6238: PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc);
6239: PetscInt *dims = mat->stencil.dims + 1;
6240: PetscInt *starts = mat->stencil.starts;
6241: PetscInt *dxm = (PetscInt *)rows;
6242: PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6248: PetscMalloc1(numRows, &jdxm);
6249: for (i = 0; i < numRows; ++i) {
6250: /* Skip unused dimensions (they are ordered k, j, i, c) */
6251: for (j = 0; j < 3 - sdim; ++j) dxm++;
6252: /* Local index in X dir */
6253: tmp = *dxm++ - starts[0];
6254: /* Loop over remaining dimensions */
6255: for (j = 0; j < dim - 1; ++j) {
6256: /* If nonlocal, set index to be negative */
6257: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6258: /* Update local index */
6259: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6260: }
6261: /* Skip component slot if necessary */
6262: if (mat->stencil.noc) dxm++;
6263: /* Local row number */
6264: if (tmp >= 0) jdxm[numNewRows++] = tmp;
6265: }
6266: MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b);
6267: PetscFree(jdxm);
6268: return 0;
6269: }
6271: /*@C
6272: MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6273: of a set of rows of a matrix; using local numbering of rows.
6275: Collective on mat
6277: Input Parameters:
6278: + mat - the matrix
6279: . numRows - the number of rows to remove
6280: . rows - the local row indices
6281: . diag - value put in all diagonals of eliminated rows
6282: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6283: - b - optional vector of right hand side, that will be adjusted by provided solution
6285: Notes:
6286: Before calling `MatZeroRowsLocal()`, the user must first set the
6287: local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6289: See `MatZeroRows()` for details on how this routine operates.
6291: Level: intermediate
6293: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6294: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6295: @*/
6296: PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6297: {
6303: MatCheckPreallocated(mat, 1);
6305: if (mat->ops->zerorowslocal) {
6306: PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6307: } else {
6308: IS is, newis;
6309: const PetscInt *newRows;
6312: ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6313: ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis);
6314: ISGetIndices(newis, &newRows);
6315: PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6316: ISRestoreIndices(newis, &newRows);
6317: ISDestroy(&newis);
6318: ISDestroy(&is);
6319: }
6320: PetscObjectStateIncrease((PetscObject)mat);
6321: return 0;
6322: }
6324: /*@
6325: MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6326: of a set of rows of a matrix; using local numbering of rows.
6328: Collective on mat
6330: Input Parameters:
6331: + mat - the matrix
6332: . is - index set of rows to remove
6333: . diag - value put in all diagonals of eliminated rows
6334: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6335: - b - optional vector of right hand side, that will be adjusted by provided solution
6337: Notes:
6338: Before calling `MatZeroRowsLocalIS()`, the user must first set the
6339: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6341: See `MatZeroRows()` for details on how this routine operates.
6343: Level: intermediate
6345: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6346: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6347: @*/
6348: PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6349: {
6350: PetscInt numRows;
6351: const PetscInt *rows;
6358: MatCheckPreallocated(mat, 1);
6360: ISGetLocalSize(is, &numRows);
6361: ISGetIndices(is, &rows);
6362: MatZeroRowsLocal(mat, numRows, rows, diag, x, b);
6363: ISRestoreIndices(is, &rows);
6364: return 0;
6365: }
6367: /*@
6368: MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6369: of a set of rows and columns of a matrix; using local numbering of rows.
6371: Collective on mat
6373: Input Parameters:
6374: + mat - the matrix
6375: . numRows - the number of rows to remove
6376: . rows - the global row indices
6377: . diag - value put in all diagonals of eliminated rows
6378: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6379: - b - optional vector of right hand side, that will be adjusted by provided solution
6381: Notes:
6382: Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6383: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6385: See `MatZeroRowsColumns()` for details on how this routine operates.
6387: Level: intermediate
6389: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6390: `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6391: @*/
6392: PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6393: {
6394: IS is, newis;
6395: const PetscInt *newRows;
6402: MatCheckPreallocated(mat, 1);
6405: ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6406: ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis);
6407: ISGetIndices(newis, &newRows);
6408: PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6409: ISRestoreIndices(newis, &newRows);
6410: ISDestroy(&newis);
6411: ISDestroy(&is);
6412: PetscObjectStateIncrease((PetscObject)mat);
6413: return 0;
6414: }
6416: /*@
6417: MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6418: of a set of rows and columns of a matrix; using local numbering of rows.
6420: Collective on Mat
6422: Input Parameters:
6423: + mat - the matrix
6424: . is - index set of rows to remove
6425: . diag - value put in all diagonals of eliminated rows
6426: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6427: - b - optional vector of right hand side, that will be adjusted by provided solution
6429: Notes:
6430: Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6431: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6433: See `MatZeroRowsColumns()` for details on how this routine operates.
6435: Level: intermediate
6437: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6438: `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6439: @*/
6440: PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6441: {
6442: PetscInt numRows;
6443: const PetscInt *rows;
6450: MatCheckPreallocated(mat, 1);
6452: ISGetLocalSize(is, &numRows);
6453: ISGetIndices(is, &rows);
6454: MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b);
6455: ISRestoreIndices(is, &rows);
6456: return 0;
6457: }
6459: /*@C
6460: MatGetSize - Returns the numbers of rows and columns in a matrix.
6462: Not Collective
6464: Input Parameter:
6465: . mat - the matrix
6467: Output Parameters:
6468: + m - the number of global rows
6469: - n - the number of global columns
6471: Note: both output parameters can be NULL on input.
6473: Level: beginner
6475: .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6476: @*/
6477: PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6478: {
6480: if (m) *m = mat->rmap->N;
6481: if (n) *n = mat->cmap->N;
6482: return 0;
6483: }
6485: /*@C
6486: MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6487: of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6489: Not Collective
6491: Input Parameter:
6492: . mat - the matrix
6494: Output Parameters:
6495: + m - the number of local rows, use `NULL` to not obtain this value
6496: - n - the number of local columns, use `NULL` to not obtain this value
6498: Level: beginner
6500: .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6501: @*/
6502: PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6503: {
6507: if (m) *m = mat->rmap->n;
6508: if (n) *n = mat->cmap->n;
6509: return 0;
6510: }
6512: /*@C
6513: MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6514: this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6516: Not Collective, unless matrix has not been allocated, then collective on mat
6518: Input Parameter:
6519: . mat - the matrix
6521: Output Parameters:
6522: + m - the global index of the first local column, use `NULL` to not obtain this value
6523: - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6525: Level: developer
6527: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6528: @*/
6529: PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6530: {
6535: MatCheckPreallocated(mat, 1);
6536: if (m) *m = mat->cmap->rstart;
6537: if (n) *n = mat->cmap->rend;
6538: return 0;
6539: }
6541: /*@C
6542: MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6543: 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
6544: vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6546: Not Collective
6548: Input Parameter:
6549: . mat - the matrix
6551: Output Parameters:
6552: + m - the global index of the first local row, use `NULL` to not obtain this value
6553: - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6555: Note:
6556: This function requires that the matrix be preallocated. If you have not preallocated, consider using
6557: `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6558: and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6560: Level: beginner
6562: .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6563: `PetscLayout`
6564: @*/
6565: PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6566: {
6571: MatCheckPreallocated(mat, 1);
6572: if (m) *m = mat->rmap->rstart;
6573: if (n) *n = mat->rmap->rend;
6574: return 0;
6575: }
6577: /*@C
6578: MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6579: 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
6580: vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6582: Not Collective, unless matrix has not been allocated, then collective on mat
6584: Input Parameters:
6585: . mat - the matrix
6587: Output Parameters:
6588: . ranges - start of each processors portion plus one more than the total length at the end
6590: Level: beginner
6592: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6593: @*/
6594: PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6595: {
6598: MatCheckPreallocated(mat, 1);
6599: PetscLayoutGetRanges(mat->rmap, ranges);
6600: return 0;
6601: }
6603: /*@C
6604: MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6605: each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6607: Not Collective, unless matrix has not been allocated, then collective on Mat
6609: Input Parameters:
6610: . mat - the matrix
6612: Output Parameters:
6613: . ranges - start of each processors portion plus one more then the total length at the end
6615: Level: beginner
6617: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6618: @*/
6619: PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6620: {
6623: MatCheckPreallocated(mat, 1);
6624: PetscLayoutGetRanges(mat->cmap, ranges);
6625: return 0;
6626: }
6628: /*@C
6629: MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6630: corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6631: is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6633: Not Collective
6635: Input Parameter:
6636: . A - matrix
6638: Output Parameters:
6639: + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6640: - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6642: Level: intermediate
6644: .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6645: @*/
6646: PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6647: {
6648: PetscErrorCode (*f)(Mat, IS *, IS *);
6650: MatCheckPreallocated(A, 1);
6651: PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f);
6652: if (f) {
6653: (*f)(A, rows, cols);
6654: } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6655: if (rows) ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows);
6656: if (cols) ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols);
6657: }
6658: return 0;
6659: }
6661: /*@C
6662: MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6663: Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6664: to complete the factorization.
6666: Collective on fact
6668: Input Parameters:
6669: + fact - the factorized matrix obtained with `MatGetFactor()`
6670: . mat - the matrix
6671: . row - row permutation
6672: . column - column permutation
6673: - info - structure containing
6674: $ levels - number of levels of fill.
6675: $ expected fill - as ratio of original fill.
6676: $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6677: missing diagonal entries)
6679: Output Parameters:
6680: . fact - new matrix that has been symbolically factored
6682: Level: developer
6684: Notes:
6685: See [Matrix Factorization](sec_matfactor) for additional information.
6687: Most users should employ the `KSP` interface for linear solvers
6688: instead of working directly with matrix algebra routines such as this.
6689: See, e.g., `KSPCreate()`.
6691: Uses the definition of level of fill as in Y. Saad, 2003
6693: Developer Note:
6694: The Fortran interface is not autogenerated as the f90
6695: interface definition cannot be generated correctly [due to `MatFactorInfo`]
6697: References:
6698: . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6700: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6701: `MatGetOrdering()`, `MatFactorInfo`
6702: @*/
6703: PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6704: {
6713: if (!fact->ops->ilufactorsymbolic) {
6714: MatSolverType stype;
6715: MatFactorGetSolverType(fact, &stype);
6716: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6717: }
6720: MatCheckPreallocated(mat, 2);
6722: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0);
6723: (fact->ops->ilufactorsymbolic)(fact, mat, row, col, info);
6724: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0);
6725: return 0;
6726: }
6728: /*@C
6729: MatICCFactorSymbolic - Performs symbolic incomplete
6730: Cholesky factorization for a symmetric matrix. Use
6731: `MatCholeskyFactorNumeric()` to complete the factorization.
6733: Collective on fact
6735: Input Parameters:
6736: + fact - the factorized matrix obtained with `MatGetFactor()`
6737: . mat - the matrix to be factored
6738: . perm - row and column permutation
6739: - info - structure containing
6740: $ levels - number of levels of fill.
6741: $ expected fill - as ratio of original fill.
6743: Output Parameter:
6744: . fact - the factored matrix
6746: Level: developer
6748: Notes:
6749: Most users should employ the `KSP` interface for linear solvers
6750: instead of working directly with matrix algebra routines such as this.
6751: See, e.g., `KSPCreate()`.
6753: This uses the definition of level of fill as in Y. Saad, 2003
6755: Developer Note:
6756: The Fortran interface is not autogenerated as the f90
6757: interface definition cannot be generated correctly [due to `MatFactorInfo`]
6759: References:
6760: . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6762: .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6763: @*/
6764: PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6765: {
6774: if (!(fact)->ops->iccfactorsymbolic) {
6775: MatSolverType stype;
6776: MatFactorGetSolverType(fact, &stype);
6777: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6778: }
6780: MatCheckPreallocated(mat, 2);
6782: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6783: (fact->ops->iccfactorsymbolic)(fact, mat, perm, info);
6784: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6785: return 0;
6786: }
6788: /*@C
6789: MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6790: points to an array of valid matrices, they may be reused to store the new
6791: submatrices.
6793: Collective on mat
6795: Input Parameters:
6796: + mat - the matrix
6797: . n - the number of submatrixes to be extracted (on this processor, may be zero)
6798: . irow, icol - index sets of rows and columns to extract
6799: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6801: Output Parameter:
6802: . submat - the array of submatrices
6804: Notes:
6805: `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6806: (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6807: to extract a parallel submatrix.
6809: Some matrix types place restrictions on the row and column
6810: indices, such as that they be sorted or that they be equal to each other.
6812: The index sets may not have duplicate entries.
6814: When extracting submatrices from a parallel matrix, each processor can
6815: form a different submatrix by setting the rows and columns of its
6816: individual index sets according to the local submatrix desired.
6818: When finished using the submatrices, the user should destroy
6819: them with `MatDestroySubMatrices()`.
6821: `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6822: original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6824: This routine creates the matrices in submat; you should NOT create them before
6825: calling it. It also allocates the array of matrix pointers submat.
6827: For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6828: request one row/column in a block, they must request all rows/columns that are in
6829: that block. For example, if the block size is 2 you cannot request just row 0 and
6830: column 0.
6832: Fortran Note:
6833: The Fortran interface is slightly different from that given below; it
6834: requires one to pass in as submat a `Mat` (integer) array of size at least n+1.
6836: Level: advanced
6838: .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6839: @*/
6840: PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6841: {
6842: PetscInt i;
6843: PetscBool eq;
6847: if (n) {
6852: }
6854: if (n && scall == MAT_REUSE_MATRIX) {
6857: }
6860: MatCheckPreallocated(mat, 1);
6861: PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6862: PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6863: PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6864: for (i = 0; i < n; i++) {
6865: (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6866: ISEqualUnsorted(irow[i], icol[i], &eq);
6867: if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6868: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
6869: if (mat->boundtocpu && mat->bindingpropagates) {
6870: MatBindToCPU((*submat)[i], PETSC_TRUE);
6871: MatSetBindingPropagates((*submat)[i], PETSC_TRUE);
6872: }
6873: #endif
6874: }
6875: return 0;
6876: }
6878: /*@C
6879: MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
6881: Collective on mat
6883: Input Parameters:
6884: + mat - the matrix
6885: . n - the number of submatrixes to be extracted
6886: . irow, icol - index sets of rows and columns to extract
6887: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6889: Output Parameter:
6890: . submat - the array of submatrices
6892: Level: advanced
6894: Note:
6895: This is used by `PCGASM`
6897: .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6898: @*/
6899: PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6900: {
6901: PetscInt i;
6902: PetscBool eq;
6906: if (n) {
6911: }
6913: if (n && scall == MAT_REUSE_MATRIX) {
6916: }
6919: MatCheckPreallocated(mat, 1);
6921: PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6922: PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6923: PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6924: for (i = 0; i < n; i++) {
6925: ISEqualUnsorted(irow[i], icol[i], &eq);
6926: if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6927: }
6928: return 0;
6929: }
6931: /*@C
6932: MatDestroyMatrices - Destroys an array of matrices.
6934: Collective on mat
6936: Input Parameters:
6937: + n - the number of local matrices
6938: - mat - the matrices (note that this is a pointer to the array of matrices)
6940: Level: advanced
6942: Note:
6943: Frees not only the matrices, but also the array that contains the matrices
6944: In Fortran will not free the array.
6946: .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6947: @*/
6948: PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
6949: {
6950: PetscInt i;
6952: if (!*mat) return 0;
6956: for (i = 0; i < n; i++) MatDestroy(&(*mat)[i]);
6958: /* memory is allocated even if n = 0 */
6959: PetscFree(*mat);
6960: return 0;
6961: }
6963: /*@C
6964: MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
6966: Collective on mat
6968: Input Parameters:
6969: + n - the number of local matrices
6970: - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
6971: sequence of MatCreateSubMatrices())
6973: Level: advanced
6975: Note:
6976: Frees not only the matrices, but also the array that contains the matrices
6977: In Fortran will not free the array.
6979: .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6980: @*/
6981: PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
6982: {
6983: Mat mat0;
6985: if (!*mat) return 0;
6986: /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
6990: mat0 = (*mat)[0];
6991: if (mat0 && mat0->ops->destroysubmatrices) {
6992: (mat0->ops->destroysubmatrices)(n, mat);
6993: } else {
6994: MatDestroyMatrices(n, mat);
6995: }
6996: return 0;
6997: }
6999: /*@C
7000: MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7002: Collective on mat
7004: Input Parameters:
7005: . mat - the matrix
7007: Output Parameter:
7008: . matstruct - the sequential matrix with the nonzero structure of mat
7010: Level: developer
7012: .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7013: @*/
7014: PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7015: {
7021: MatCheckPreallocated(mat, 1);
7023: PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7024: PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7025: PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7026: return 0;
7027: }
7029: /*@C
7030: MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7032: Collective on mat
7034: Input Parameters:
7035: . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7036: sequence of `MatGetSequentialNonzeroStructure()`)
7038: Level: advanced
7040: Note:
7041: Frees not only the matrices, but also the array that contains the matrices
7043: .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7044: @*/
7045: PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7046: {
7048: MatDestroy(mat);
7049: return 0;
7050: }
7052: /*@
7053: MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7054: replaces the index sets by larger ones that represent submatrices with
7055: additional overlap.
7057: Collective on mat
7059: Input Parameters:
7060: + mat - the matrix
7061: . n - the number of index sets
7062: . is - the array of index sets (these index sets will changed during the call)
7063: - ov - the additional overlap requested
7065: Options Database:
7066: . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7068: Level: developer
7070: Developer Note:
7071: 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.
7073: .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7074: @*/
7075: PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7076: {
7077: PetscInt i, bs, cbs;
7083: if (n) {
7086: }
7089: MatCheckPreallocated(mat, 1);
7091: if (!ov || !n) return 0;
7092: PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7093: PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7094: PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7095: MatGetBlockSizes(mat, &bs, &cbs);
7096: if (bs == cbs) {
7097: for (i = 0; i < n; i++) ISSetBlockSize(is[i], bs);
7098: }
7099: return 0;
7100: }
7102: PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7104: /*@
7105: MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7106: a sub communicator, replaces the index sets by larger ones that represent submatrices with
7107: additional overlap.
7109: Collective on mat
7111: Input Parameters:
7112: + mat - the matrix
7113: . n - the number of index sets
7114: . is - the array of index sets (these index sets will changed during the call)
7115: - ov - the additional overlap requested
7117: ` Options Database:
7118: . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7120: Level: developer
7122: .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7123: @*/
7124: PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7125: {
7126: PetscInt i;
7131: if (n) {
7134: }
7137: MatCheckPreallocated(mat, 1);
7138: if (!ov) return 0;
7139: PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7140: for (i = 0; i < n; i++) MatIncreaseOverlapSplit_Single(mat, &is[i], ov);
7141: PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7142: return 0;
7143: }
7145: /*@
7146: MatGetBlockSize - Returns the matrix block size.
7148: Not Collective
7150: Input Parameter:
7151: . mat - the matrix
7153: Output Parameter:
7154: . bs - block size
7156: Notes:
7157: Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7159: If the block size has not been set yet this routine returns 1.
7161: Level: intermediate
7163: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7164: @*/
7165: PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7166: {
7169: *bs = PetscAbs(mat->rmap->bs);
7170: return 0;
7171: }
7173: /*@
7174: MatGetBlockSizes - Returns the matrix block row and column sizes.
7176: Not Collective
7178: Input Parameter:
7179: . mat - the matrix
7181: Output Parameters:
7182: + rbs - row block size
7183: - cbs - column block size
7185: Notes:
7186: Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7187: If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7189: If a block size has not been set yet this routine returns 1.
7191: Level: intermediate
7193: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7194: @*/
7195: PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7196: {
7200: if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7201: if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7202: return 0;
7203: }
7205: /*@
7206: MatSetBlockSize - Sets the matrix block size.
7208: Logically Collective on mat
7210: Input Parameters:
7211: + mat - the matrix
7212: - bs - block size
7214: Notes:
7215: Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7216: This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7218: For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7219: is compatible with the matrix local sizes.
7221: Level: intermediate
7223: .seealso: `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7224: @*/
7225: PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7226: {
7229: MatSetBlockSizes(mat, bs, bs);
7230: return 0;
7231: }
7233: typedef struct {
7234: PetscInt n;
7235: IS *is;
7236: Mat *mat;
7237: PetscObjectState nonzerostate;
7238: Mat C;
7239: } EnvelopeData;
7241: static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7242: {
7243: for (PetscInt i = 0; i < edata->n; i++) ISDestroy(&edata->is[i]);
7244: PetscFree(edata->is);
7245: PetscFree(edata);
7246: return 0;
7247: }
7249: /*
7250: MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7251: the sizes of these blocks in the matrix. An individual block may lie over several processes.
7253: Collective on mat
7255: Input Parameter:
7256: . mat - the matrix
7258: Notes:
7259: There can be zeros within the blocks
7261: The blocks can overlap between processes, including laying on more than two processes
7263: .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7264: */
7265: static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7266: {
7267: PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7268: PetscInt *diag, *odiag, sc;
7269: VecScatter scatter;
7270: PetscScalar *seqv;
7271: const PetscScalar *parv;
7272: const PetscInt *ia, *ja;
7273: PetscBool set, flag, done;
7274: Mat AA = mat, A;
7275: MPI_Comm comm;
7276: PetscMPIInt rank, size, tag;
7277: MPI_Status status;
7278: PetscContainer container;
7279: EnvelopeData *edata;
7280: Vec seq, par;
7281: IS isglobal;
7284: MatIsSymmetricKnown(mat, &set, &flag);
7285: if (!set || !flag) {
7286: /* TOO: only needs nonzero structure of transpose */
7287: MatTranspose(mat, MAT_INITIAL_MATRIX, &AA);
7288: MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN);
7289: }
7290: MatAIJGetLocalMat(AA, &A);
7291: MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7294: MatGetLocalSize(mat, &n, NULL);
7295: PetscObjectGetNewTag((PetscObject)mat, &tag);
7296: PetscObjectGetComm((PetscObject)mat, &comm);
7297: MPI_Comm_size(comm, &size);
7298: MPI_Comm_rank(comm, &rank);
7300: PetscMalloc2(n, &sizes, n, &starts);
7302: if (rank > 0) {
7303: MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status);
7304: MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status);
7305: }
7306: MatGetOwnershipRange(mat, &rstart, NULL);
7307: for (i = 0; i < n; i++) {
7308: env = PetscMax(env, ja[ia[i + 1] - 1]);
7309: II = rstart + i;
7310: if (env == II) {
7311: starts[lblocks] = tbs;
7312: sizes[lblocks++] = 1 + II - tbs;
7313: tbs = 1 + II;
7314: }
7315: }
7316: if (rank < size - 1) {
7317: MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm);
7318: MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm);
7319: }
7321: MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7322: if (!set || !flag) MatDestroy(&AA);
7323: MatDestroy(&A);
7325: PetscNew(&edata);
7326: MatGetNonzeroState(mat, &edata->nonzerostate);
7327: edata->n = lblocks;
7328: /* create IS needed for extracting blocks from the original matrix */
7329: PetscMalloc1(lblocks, &edata->is);
7330: for (PetscInt i = 0; i < lblocks; i++) ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]);
7332: /* Create the resulting inverse matrix structure with preallocation information */
7333: MatCreate(PetscObjectComm((PetscObject)mat), &edata->C);
7334: MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
7335: MatSetBlockSizesFromMats(edata->C, mat, mat);
7336: MatSetType(edata->C, MATAIJ);
7338: /* Communicate the start and end of each row, from each block to the correct rank */
7339: /* TODO: Use PetscSF instead of VecScatter */
7340: for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7341: VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq);
7342: VecGetArrayWrite(seq, &seqv);
7343: for (PetscInt i = 0; i < lblocks; i++) {
7344: for (PetscInt j = 0; j < sizes[i]; j++) {
7345: seqv[cnt] = starts[i];
7346: seqv[cnt + 1] = starts[i] + sizes[i];
7347: cnt += 2;
7348: }
7349: }
7350: VecRestoreArrayWrite(seq, &seqv);
7351: MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
7352: sc -= cnt;
7353: VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par);
7354: ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal);
7355: VecScatterCreate(seq, NULL, par, isglobal, &scatter);
7356: ISDestroy(&isglobal);
7357: VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7358: VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7359: VecScatterDestroy(&scatter);
7360: VecDestroy(&seq);
7361: MatGetOwnershipRangeColumn(mat, &cstart, &cend);
7362: PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag);
7363: VecGetArrayRead(par, &parv);
7364: cnt = 0;
7365: MatGetSize(mat, NULL, &n);
7366: for (PetscInt i = 0; i < mat->rmap->n; i++) {
7367: PetscInt start, end, d = 0, od = 0;
7369: start = (PetscInt)PetscRealPart(parv[cnt]);
7370: end = (PetscInt)PetscRealPart(parv[cnt + 1]);
7371: cnt += 2;
7373: if (start < cstart) {
7374: od += cstart - start + n - cend;
7375: d += cend - cstart;
7376: } else if (start < cend) {
7377: od += n - cend;
7378: d += cend - start;
7379: } else od += n - start;
7380: if (end <= cstart) {
7381: od -= cstart - end + n - cend;
7382: d -= cend - cstart;
7383: } else if (end < cend) {
7384: od -= n - cend;
7385: d -= cend - end;
7386: } else od -= n - end;
7388: odiag[i] = od;
7389: diag[i] = d;
7390: }
7391: VecRestoreArrayRead(par, &parv);
7392: VecDestroy(&par);
7393: MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL);
7394: PetscFree2(diag, odiag);
7395: PetscFree2(sizes, starts);
7397: PetscContainerCreate(PETSC_COMM_SELF, &container);
7398: PetscContainerSetPointer(container, edata);
7399: PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy);
7400: PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container);
7401: PetscObjectDereference((PetscObject)container);
7402: return 0;
7403: }
7405: /*@
7406: MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7408: Collective on A
7410: Input Parameters:
7411: . A - the matrix
7413: Output Parameters:
7414: . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set.
7416: Note:
7417: For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7419: Level: advanced
7421: .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7422: @*/
7423: PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7424: {
7425: PetscContainer container;
7426: EnvelopeData *edata;
7427: PetscObjectState nonzerostate;
7429: PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7430: if (!container) {
7431: MatComputeVariableBlockEnvelope(A);
7432: PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7433: }
7434: PetscContainerGetPointer(container, (void **)&edata);
7435: MatGetNonzeroState(A, &nonzerostate);
7439: MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat);
7440: *C = edata->C;
7442: for (PetscInt i = 0; i < edata->n; i++) {
7443: Mat D;
7444: PetscScalar *dvalues;
7446: MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D);
7447: MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE);
7448: MatSeqDenseInvert(D);
7449: MatDenseGetArray(D, &dvalues);
7450: MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES);
7451: MatDestroy(&D);
7452: }
7453: MatDestroySubMatrices(edata->n, &edata->mat);
7454: MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY);
7455: MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY);
7456: return 0;
7457: }
7459: /*@
7460: MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7462: Logically Collective on mat
7464: Input Parameters:
7465: + mat - the matrix
7466: . nblocks - the number of blocks on this process, each block can only exist on a single process
7467: - bsizes - the block sizes
7469: Notes:
7470: Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7472: 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.
7474: Level: intermediate
7476: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7477: `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7478: @*/
7479: PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7480: {
7481: PetscInt i, ncnt = 0, nlocal;
7485: MatGetLocalSize(mat, &nlocal, NULL);
7486: for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7488: PetscFree(mat->bsizes);
7489: mat->nblocks = nblocks;
7490: PetscMalloc1(nblocks, &mat->bsizes);
7491: PetscArraycpy(mat->bsizes, bsizes, nblocks);
7492: return 0;
7493: }
7495: /*@C
7496: MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7498: Logically Collective on mat
7500: Input Parameter:
7501: . mat - the matrix
7503: Output Parameters:
7504: + nblocks - the number of blocks on this process
7505: - bsizes - the block sizes
7507: Fortran Note:
7508: Currently not supported from Fortran
7510: Level: intermediate
7512: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7513: @*/
7514: PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7515: {
7517: *nblocks = mat->nblocks;
7518: *bsizes = mat->bsizes;
7519: return 0;
7520: }
7522: /*@
7523: MatSetBlockSizes - Sets the matrix block row and column sizes.
7525: Logically Collective on mat
7527: Input Parameters:
7528: + mat - the matrix
7529: . rbs - row block size
7530: - cbs - column block size
7532: Notes:
7533: Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7534: If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7535: This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7537: For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7538: are compatible with the matrix local sizes.
7540: The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7542: Level: intermediate
7544: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7545: @*/
7546: PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7547: {
7551: PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7552: if (mat->rmap->refcnt) {
7553: ISLocalToGlobalMapping l2g = NULL;
7554: PetscLayout nmap = NULL;
7556: PetscLayoutDuplicate(mat->rmap, &nmap);
7557: if (mat->rmap->mapping) ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g);
7558: PetscLayoutDestroy(&mat->rmap);
7559: mat->rmap = nmap;
7560: mat->rmap->mapping = l2g;
7561: }
7562: if (mat->cmap->refcnt) {
7563: ISLocalToGlobalMapping l2g = NULL;
7564: PetscLayout nmap = NULL;
7566: PetscLayoutDuplicate(mat->cmap, &nmap);
7567: if (mat->cmap->mapping) ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g);
7568: PetscLayoutDestroy(&mat->cmap);
7569: mat->cmap = nmap;
7570: mat->cmap->mapping = l2g;
7571: }
7572: PetscLayoutSetBlockSize(mat->rmap, rbs);
7573: PetscLayoutSetBlockSize(mat->cmap, cbs);
7574: return 0;
7575: }
7577: /*@
7578: MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7580: Logically Collective on mat
7582: Input Parameters:
7583: + mat - the matrix
7584: . fromRow - matrix from which to copy row block size
7585: - fromCol - matrix from which to copy column block size (can be same as fromRow)
7587: Level: developer
7589: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7590: @*/
7591: PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7592: {
7596: if (fromRow->rmap->bs > 0) PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs);
7597: if (fromCol->cmap->bs > 0) PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs);
7598: return 0;
7599: }
7601: /*@
7602: MatResidual - Default routine to calculate the residual r = b - Ax
7604: Collective on mat
7606: Input Parameters:
7607: + mat - the matrix
7608: . b - the right-hand-side
7609: - x - the approximate solution
7611: Output Parameter:
7612: . r - location to store the residual
7614: Level: developer
7616: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7617: @*/
7618: PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7619: {
7625: MatCheckPreallocated(mat, 1);
7626: PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0);
7627: if (!mat->ops->residual) {
7628: MatMult(mat, x, r);
7629: VecAYPX(r, -1.0, b);
7630: } else {
7631: PetscUseTypeMethod(mat, residual, b, x, r);
7632: }
7633: PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0);
7634: return 0;
7635: }
7637: /*@C
7638: MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7640: Collective on mat
7642: Input Parameters:
7643: + mat - the matrix
7644: . shift - 0 or 1 indicating we want the indices starting at 0 or 1
7645: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7646: - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the
7647: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7648: always used.
7650: Output Parameters:
7651: + n - number of local rows in the (possibly compressed) matrix, use NULL if not needed
7652: . 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
7653: . ja - the column indices, use NULL if not needed
7654: - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7655: are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7657: Level: developer
7659: Notes:
7660: You CANNOT change any of the ia[] or ja[] values.
7662: Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7664: Fortran Notes:
7665: In Fortran use
7666: $
7667: $ PetscInt ia(1), ja(1)
7668: $ PetscOffset iia, jja
7669: $ call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7670: $ ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7672: or
7673: $
7674: $ PetscInt, pointer :: ia(:),ja(:)
7675: $ call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7676: $ ! Access the ith and jth entries via ia(i) and ja(j)
7678: .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7679: @*/
7680: PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7681: {
7688: MatCheckPreallocated(mat, 1);
7689: if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7690: else {
7691: if (done) *done = PETSC_TRUE;
7692: PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0);
7693: PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7694: PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0);
7695: }
7696: return 0;
7697: }
7699: /*@C
7700: MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7702: Collective on mat
7704: Input Parameters:
7705: + mat - the matrix
7706: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7707: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7708: symmetrized
7709: . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7710: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7711: always used.
7712: . n - number of columns in the (possibly compressed) matrix
7713: . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7714: - ja - the row indices
7716: Output Parameters:
7717: . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7719: Level: developer
7721: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7722: @*/
7723: PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7724: {
7731: MatCheckPreallocated(mat, 1);
7732: if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7733: else {
7734: *done = PETSC_TRUE;
7735: PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7736: }
7737: return 0;
7738: }
7740: /*@C
7741: MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7743: Collective on mat
7745: Input Parameters:
7746: + mat - the matrix
7747: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7748: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7749: . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7750: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7751: always used.
7752: . n - size of (possibly compressed) matrix
7753: . ia - the row pointers
7754: - ja - the column indices
7756: Output Parameters:
7757: . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7759: Note:
7760: This routine zeros out n, ia, and ja. This is to prevent accidental
7761: us of the array after it has been restored. If you pass NULL, it will
7762: not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7764: Level: developer
7766: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7767: @*/
7768: PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7769: {
7775: MatCheckPreallocated(mat, 1);
7777: if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7778: else {
7779: if (done) *done = PETSC_TRUE;
7780: PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7781: if (n) *n = 0;
7782: if (ia) *ia = NULL;
7783: if (ja) *ja = NULL;
7784: }
7785: return 0;
7786: }
7788: /*@C
7789: MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
7791: Collective on Mat
7793: Input Parameters:
7794: + mat - the matrix
7795: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7796: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7797: - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7798: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7799: always used.
7801: Output Parameters:
7802: + n - size of (possibly compressed) matrix
7803: . ia - the column pointers
7804: . ja - the row indices
7805: - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7807: Level: developer
7809: .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7810: @*/
7811: PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7812: {
7818: MatCheckPreallocated(mat, 1);
7820: if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7821: else {
7822: *done = PETSC_TRUE;
7823: PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7824: if (n) *n = 0;
7825: if (ia) *ia = NULL;
7826: if (ja) *ja = NULL;
7827: }
7828: return 0;
7829: }
7831: /*@C
7832: MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
7834: Collective on mat
7836: Input Parameters:
7837: + mat - the matrix
7838: . ncolors - max color value
7839: . n - number of entries in colorarray
7840: - colorarray - array indicating color for each column
7842: Output Parameters:
7843: . iscoloring - coloring generated using colorarray information
7845: Level: developer
7847: .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7848: @*/
7849: PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
7850: {
7855: MatCheckPreallocated(mat, 1);
7857: if (!mat->ops->coloringpatch) {
7858: ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring);
7859: } else {
7860: PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7861: }
7862: return 0;
7863: }
7865: /*@
7866: MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
7868: Logically Collective on mat
7870: Input Parameter:
7871: . mat - the factored matrix to be reset
7873: Notes:
7874: This routine should be used only with factored matrices formed by in-place
7875: factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
7876: format). This option can save memory, for example, when solving nonlinear
7877: systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7878: ILU(0) preconditioner.
7880: Note that one can specify in-place ILU(0) factorization by calling
7881: .vb
7882: PCType(pc,PCILU);
7883: PCFactorSeUseInPlace(pc);
7884: .ve
7885: or by using the options -pc_type ilu -pc_factor_in_place
7887: In-place factorization ILU(0) can also be used as a local
7888: solver for the blocks within the block Jacobi or additive Schwarz
7889: methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc
7890: for details on setting local solver options.
7892: Most users should employ the `KSP` interface for linear solvers
7893: instead of working directly with matrix algebra routines such as this.
7894: See, e.g., `KSPCreate()`.
7896: Level: developer
7898: .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7899: @*/
7900: PetscErrorCode MatSetUnfactored(Mat mat)
7901: {
7904: MatCheckPreallocated(mat, 1);
7905: mat->factortype = MAT_FACTOR_NONE;
7906: if (!mat->ops->setunfactored) return 0;
7907: PetscUseTypeMethod(mat, setunfactored);
7908: return 0;
7909: }
7911: /*MC
7912: MatDenseGetArrayF90 - Accesses a matrix array from Fortran
7914: Synopsis:
7915: MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7917: Not collective
7919: Input Parameter:
7920: . x - matrix
7922: Output Parameters:
7923: + xx_v - the Fortran pointer to the array
7924: - ierr - error code
7926: Example of Usage:
7927: .vb
7928: PetscScalar, pointer xx_v(:,:)
7929: ....
7930: call MatDenseGetArrayF90(x,xx_v,ierr)
7931: a = xx_v(3)
7932: call MatDenseRestoreArrayF90(x,xx_v,ierr)
7933: .ve
7935: Level: advanced
7937: .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
7939: M*/
7941: /*MC
7942: MatDenseRestoreArrayF90 - Restores a matrix array that has been
7943: accessed with `MatDenseGetArrayF90()`.
7945: Synopsis:
7946: MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7948: Not collective
7950: Input Parameters:
7951: + x - matrix
7952: - xx_v - the Fortran90 pointer to the array
7954: Output Parameter:
7955: . ierr - error code
7957: Example of Usage:
7958: .vb
7959: PetscScalar, pointer xx_v(:,:)
7960: ....
7961: call MatDenseGetArrayF90(x,xx_v,ierr)
7962: a = xx_v(3)
7963: call MatDenseRestoreArrayF90(x,xx_v,ierr)
7964: .ve
7966: Level: advanced
7968: .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
7970: M*/
7972: /*MC
7973: MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
7975: Synopsis:
7976: MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7978: Not collective
7980: Input Parameter:
7981: . x - matrix
7983: Output Parameters:
7984: + xx_v - the Fortran pointer to the array
7985: - ierr - error code
7987: Example of Usage:
7988: .vb
7989: PetscScalar, pointer xx_v(:)
7990: ....
7991: call MatSeqAIJGetArrayF90(x,xx_v,ierr)
7992: a = xx_v(3)
7993: call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
7994: .ve
7996: Level: advanced
7998: .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8000: M*/
8002: /*MC
8003: MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8004: accessed with `MatSeqAIJGetArrayF90()`.
8006: Synopsis:
8007: MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8009: Not collective
8011: Input Parameters:
8012: + x - matrix
8013: - xx_v - the Fortran90 pointer to the array
8015: Output Parameter:
8016: . ierr - error code
8018: Example of Usage:
8019: .vb
8020: PetscScalar, pointer xx_v(:)
8021: ....
8022: call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8023: a = xx_v(3)
8024: call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8025: .ve
8027: Level: advanced
8029: .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8031: M*/
8033: /*@
8034: MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8035: as the original matrix.
8037: Collective on mat
8039: Input Parameters:
8040: + mat - the original matrix
8041: . isrow - parallel IS containing the rows this processor should obtain
8042: . 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.
8043: - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8045: Output Parameter:
8046: . newmat - the new submatrix, of the same type as the old
8048: Level: advanced
8050: Notes:
8051: The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8053: Some matrix types place restrictions on the row and column indices, such
8054: as that they be sorted or that they be equal to each other.
8056: The index sets may not have duplicate entries.
8058: The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8059: the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8060: to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8061: will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when
8062: you are finished using it.
8064: The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8065: the input matrix.
8067: If iscol is NULL then all columns are obtained (not supported in Fortran).
8069: Example usage:
8070: Consider the following 8x8 matrix with 34 non-zero values, that is
8071: assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8072: proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8073: as follows:
8075: .vb
8076: 1 2 0 | 0 3 0 | 0 4
8077: Proc0 0 5 6 | 7 0 0 | 8 0
8078: 9 0 10 | 11 0 0 | 12 0
8079: -------------------------------------
8080: 13 0 14 | 15 16 17 | 0 0
8081: Proc1 0 18 0 | 19 20 21 | 0 0
8082: 0 0 0 | 22 23 0 | 24 0
8083: -------------------------------------
8084: Proc2 25 26 27 | 0 0 28 | 29 0
8085: 30 0 0 | 31 32 33 | 0 34
8086: .ve
8088: Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is
8090: .vb
8091: 2 0 | 0 3 0 | 0
8092: Proc0 5 6 | 7 0 0 | 8
8093: -------------------------------
8094: Proc1 18 0 | 19 20 21 | 0
8095: -------------------------------
8096: Proc2 26 27 | 0 0 28 | 29
8097: 0 0 | 31 32 33 | 0
8098: .ve
8100: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8101: @*/
8102: PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8103: {
8104: PetscMPIInt size;
8105: Mat *local;
8106: IS iscoltmp;
8107: PetscBool flg;
8118: MatCheckPreallocated(mat, 1);
8119: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8121: if (!iscol || isrow == iscol) {
8122: PetscBool stride;
8123: PetscMPIInt grabentirematrix = 0, grab;
8124: PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride);
8125: if (stride) {
8126: PetscInt first, step, n, rstart, rend;
8127: ISStrideGetInfo(isrow, &first, &step);
8128: if (step == 1) {
8129: MatGetOwnershipRange(mat, &rstart, &rend);
8130: if (rstart == first) {
8131: ISGetLocalSize(isrow, &n);
8132: if (n == rend - rstart) grabentirematrix = 1;
8133: }
8134: }
8135: }
8136: MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat));
8137: if (grab) {
8138: PetscInfo(mat, "Getting entire matrix as submatrix\n");
8139: if (cll == MAT_INITIAL_MATRIX) {
8140: *newmat = mat;
8141: PetscObjectReference((PetscObject)mat);
8142: }
8143: return 0;
8144: }
8145: }
8147: if (!iscol) {
8148: ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp);
8149: } else {
8150: iscoltmp = iscol;
8151: }
8153: /* if original matrix is on just one processor then use submatrix generated */
8154: if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8155: MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat);
8156: goto setproperties;
8157: } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8158: MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local);
8159: *newmat = *local;
8160: PetscFree(local);
8161: goto setproperties;
8162: } else if (!mat->ops->createsubmatrix) {
8163: /* Create a new matrix type that implements the operation using the full matrix */
8164: PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8165: switch (cll) {
8166: case MAT_INITIAL_MATRIX:
8167: MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat);
8168: break;
8169: case MAT_REUSE_MATRIX:
8170: MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp);
8171: break;
8172: default:
8173: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8174: }
8175: PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8176: goto setproperties;
8177: }
8179: PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8180: PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8181: PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8183: setproperties:
8184: ISEqualUnsorted(isrow, iscoltmp, &flg);
8185: if (flg) MatPropagateSymmetryOptions(mat, *newmat);
8186: if (!iscol) ISDestroy(&iscoltmp);
8187: if (*newmat && cll == MAT_INITIAL_MATRIX) PetscObjectStateIncrease((PetscObject)*newmat);
8188: return 0;
8189: }
8191: /*@
8192: MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8194: Not Collective
8196: Input Parameters:
8197: + A - the matrix we wish to propagate options from
8198: - B - the matrix we wish to propagate options to
8200: Level: beginner
8202: Note:
8203: Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8205: .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8206: @*/
8207: PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8208: {
8211: B->symmetry_eternal = A->symmetry_eternal;
8212: B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8213: B->symmetric = A->symmetric;
8214: B->structurally_symmetric = A->structurally_symmetric;
8215: B->spd = A->spd;
8216: B->hermitian = A->hermitian;
8217: return 0;
8218: }
8220: /*@
8221: MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8222: used during the assembly process to store values that belong to
8223: other processors.
8225: Not Collective
8227: Input Parameters:
8228: + mat - the matrix
8229: . size - the initial size of the stash.
8230: - bsize - the initial size of the block-stash(if used).
8232: Options Database Keys:
8233: + -matstash_initial_size <size> or <size0,size1,...sizep-1>
8234: - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1>
8236: Level: intermediate
8238: Notes:
8239: The block-stash is used for values set with `MatSetValuesBlocked()` while
8240: the stash is used for values set with `MatSetValues()`
8242: Run with the option -info and look for output of the form
8243: MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8244: to determine the appropriate value, MM, to use for size and
8245: MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8246: to determine the value, BMM to use for bsize
8248: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8249: @*/
8250: PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8251: {
8254: MatStashSetInitialSize_Private(&mat->stash, size);
8255: MatStashSetInitialSize_Private(&mat->bstash, bsize);
8256: return 0;
8257: }
8259: /*@
8260: MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8261: the matrix
8263: Neighbor-wise Collective on mat
8265: Input Parameters:
8266: + mat - the matrix
8267: . x,y - the vectors
8268: - w - where the result is stored
8270: Level: intermediate
8272: Notes:
8273: w may be the same vector as y.
8275: This allows one to use either the restriction or interpolation (its transpose)
8276: matrix to do the interpolation
8278: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8279: @*/
8280: PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8281: {
8282: PetscInt M, N, Ny;
8288: MatGetSize(A, &M, &N);
8289: VecGetSize(y, &Ny);
8290: if (M == Ny) {
8291: MatMultAdd(A, x, y, w);
8292: } else {
8293: MatMultTransposeAdd(A, x, y, w);
8294: }
8295: return 0;
8296: }
8298: /*@
8299: MatInterpolate - y = A*x or A'*x depending on the shape of
8300: the matrix
8302: Neighbor-wise Collective on mat
8304: Input Parameters:
8305: + mat - the matrix
8306: - x,y - the vectors
8308: Level: intermediate
8310: Note:
8311: This allows one to use either the restriction or interpolation (its transpose)
8312: matrix to do the interpolation
8314: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8315: @*/
8316: PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8317: {
8318: PetscInt M, N, Ny;
8323: MatGetSize(A, &M, &N);
8324: VecGetSize(y, &Ny);
8325: if (M == Ny) {
8326: MatMult(A, x, y);
8327: } else {
8328: MatMultTranspose(A, x, y);
8329: }
8330: return 0;
8331: }
8333: /*@
8334: MatRestrict - y = A*x or A'*x
8336: Neighbor-wise Collective on Mat
8338: Input Parameters:
8339: + mat - the matrix
8340: - x,y - the vectors
8342: Level: intermediate
8344: Note:
8345: This allows one to use either the restriction or interpolation (its transpose)
8346: matrix to do the restriction
8348: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8349: @*/
8350: PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8351: {
8352: PetscInt M, N, Ny;
8357: MatGetSize(A, &M, &N);
8358: VecGetSize(y, &Ny);
8359: if (M == Ny) {
8360: MatMult(A, x, y);
8361: } else {
8362: MatMultTranspose(A, x, y);
8363: }
8364: return 0;
8365: }
8367: /*@
8368: MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8370: Neighbor-wise Collective on Mat
8372: Input Parameters:
8373: + mat - the matrix
8374: - w, x - the input dense matrices
8376: Output Parameters:
8377: . y - the output dense matrix
8379: Level: intermediate
8381: Note:
8382: This allows one to use either the restriction or interpolation (its transpose)
8383: matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8384: otherwise it will be recreated. y must be initialized to NULL if not supplied.
8386: .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8387: @*/
8388: PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8389: {
8390: PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8391: PetscBool trans = PETSC_TRUE;
8392: MatReuse reuse = MAT_INITIAL_MATRIX;
8399: MatGetSize(A, &M, &N);
8400: MatGetSize(x, &Mx, &Nx);
8401: if (N == Mx) trans = PETSC_FALSE;
8403: Mo = trans ? N : M;
8404: if (*y) {
8405: MatGetSize(*y, &My, &Ny);
8406: if (Mo == My && Nx == Ny) {
8407: reuse = MAT_REUSE_MATRIX;
8408: } else {
8410: MatDestroy(y);
8411: }
8412: }
8414: if (w && *y == w) { /* this is to minimize changes in PCMG */
8415: PetscBool flg;
8417: PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w);
8418: if (w) {
8419: PetscInt My, Ny, Mw, Nw;
8421: PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg);
8422: MatGetSize(*y, &My, &Ny);
8423: MatGetSize(w, &Mw, &Nw);
8424: if (!flg || My != Mw || Ny != Nw) w = NULL;
8425: }
8426: if (!w) {
8427: MatDuplicate(*y, MAT_COPY_VALUES, &w);
8428: PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w);
8429: PetscObjectDereference((PetscObject)w);
8430: } else {
8431: MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN);
8432: }
8433: }
8434: if (!trans) {
8435: MatMatMult(A, x, reuse, PETSC_DEFAULT, y);
8436: } else {
8437: MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y);
8438: }
8439: if (w) MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN);
8440: return 0;
8441: }
8443: /*@
8444: MatMatInterpolate - Y = A*X or A'*X
8446: Neighbor-wise Collective on Mat
8448: Input Parameters:
8449: + mat - the matrix
8450: - x - the input dense matrix
8452: Output Parameters:
8453: . y - the output dense matrix
8455: Level: intermediate
8457: Note:
8458: This allows one to use either the restriction or interpolation (its transpose)
8459: matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8460: otherwise it will be recreated. y must be initialized to NULL if not supplied.
8462: .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8463: @*/
8464: PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8465: {
8466: MatMatInterpolateAdd(A, x, NULL, y);
8467: return 0;
8468: }
8470: /*@
8471: MatMatRestrict - Y = A*X or A'*X
8473: Neighbor-wise Collective on Mat
8475: Input Parameters:
8476: + mat - the matrix
8477: - x - the input dense matrix
8479: Output Parameters:
8480: . y - the output dense matrix
8482: Level: intermediate
8484: Note:
8485: This allows one to use either the restriction or interpolation (its transpose)
8486: matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8487: otherwise it will be recreated. y must be initialized to NULL if not supplied.
8489: .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8490: @*/
8491: PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8492: {
8493: MatMatInterpolateAdd(A, x, NULL, y);
8494: return 0;
8495: }
8497: /*@
8498: MatGetNullSpace - retrieves the null space of a matrix.
8500: Logically Collective on mat
8502: Input Parameters:
8503: + mat - the matrix
8504: - nullsp - the null space object
8506: Level: developer
8508: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8509: @*/
8510: PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8511: {
8514: *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8515: return 0;
8516: }
8518: /*@
8519: MatSetNullSpace - attaches a null space to a matrix.
8521: Logically Collective on mat
8523: Input Parameters:
8524: + mat - the matrix
8525: - nullsp - the null space object
8527: Level: advanced
8529: Notes:
8530: This null space is used by the `KSP` linear solvers to solve singular systems.
8532: 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
8534: 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
8535: to zero but the linear system will still be solved in a least squares sense.
8537: The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8538: 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).
8539: 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
8540: 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
8541: 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).
8542: This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8544: If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8545: `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8546: routine also automatically calls `MatSetTransposeNullSpace()`.
8548: The user should call `MatNullSpaceDestroy()`.
8550: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8551: `KSPSetPCSide()`
8552: @*/
8553: PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8554: {
8557: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8558: MatNullSpaceDestroy(&mat->nullsp);
8559: mat->nullsp = nullsp;
8560: if (mat->symmetric == PETSC_BOOL3_TRUE) MatSetTransposeNullSpace(mat, nullsp);
8561: return 0;
8562: }
8564: /*@
8565: MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8567: Logically Collective on mat
8569: Input Parameters:
8570: + mat - the matrix
8571: - nullsp - the null space object
8573: Level: developer
8575: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8576: @*/
8577: PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8578: {
8582: *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8583: return 0;
8584: }
8586: /*@
8587: MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8589: Logically Collective on mat
8591: Input Parameters:
8592: + mat - the matrix
8593: - nullsp - the null space object
8595: Level: advanced
8597: Notes:
8598: This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8600: See `MatSetNullSpace()`
8602: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8603: @*/
8604: PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8605: {
8608: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8609: MatNullSpaceDestroy(&mat->transnullsp);
8610: mat->transnullsp = nullsp;
8611: return 0;
8612: }
8614: /*@
8615: MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8616: This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8618: Logically Collective on mat
8620: Input Parameters:
8621: + mat - the matrix
8622: - nullsp - the null space object
8624: Level: advanced
8626: Notes:
8627: Overwrites any previous near null space that may have been attached
8629: You can remove the null space by calling this routine with an nullsp of NULL
8631: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8632: @*/
8633: PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8634: {
8638: MatCheckPreallocated(mat, 1);
8639: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8640: MatNullSpaceDestroy(&mat->nearnullsp);
8641: mat->nearnullsp = nullsp;
8642: return 0;
8643: }
8645: /*@
8646: MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8648: Not Collective
8650: Input Parameter:
8651: . mat - the matrix
8653: Output Parameter:
8654: . nullsp - the null space object, NULL if not set
8656: Level: advanced
8658: .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8659: @*/
8660: PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8661: {
8665: MatCheckPreallocated(mat, 1);
8666: *nullsp = mat->nearnullsp;
8667: return 0;
8668: }
8670: /*@C
8671: MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8673: Collective on mat
8675: Input Parameters:
8676: + mat - the matrix
8677: . row - row/column permutation
8678: . fill - expected fill factor >= 1.0
8679: - level - level of fill, for ICC(k)
8681: Notes:
8682: Probably really in-place only when level of fill is zero, otherwise allocates
8683: new space to store factored matrix and deletes previous memory.
8685: Most users should employ the `KSP` interface for linear solvers
8686: instead of working directly with matrix algebra routines such as this.
8687: See, e.g., `KSPCreate()`.
8689: Level: developer
8691: Developer Note:
8692: The Fortran interface is not autogenerated as the f90
8693: interface definition cannot be generated correctly [due to `MatFactorInfo`]
8695: .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8696: @*/
8697: PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8698: {
8706: MatCheckPreallocated(mat, 1);
8707: PetscUseTypeMethod(mat, iccfactor, row, info);
8708: PetscObjectStateIncrease((PetscObject)mat);
8709: return 0;
8710: }
8712: /*@
8713: MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8714: ghosted ones.
8716: Not Collective
8718: Input Parameters:
8719: + mat - the matrix
8720: - diag - the diagonal values, including ghost ones
8722: Level: developer
8724: Notes:
8725: Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8727: This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8729: .seealso: `MatDiagonalScale()`
8730: @*/
8731: PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8732: {
8733: PetscMPIInt size;
8740: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
8741: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8742: if (size == 1) {
8743: PetscInt n, m;
8744: VecGetSize(diag, &n);
8745: MatGetSize(mat, NULL, &m);
8746: if (m == n) {
8747: MatDiagonalScale(mat, NULL, diag);
8748: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8749: } else {
8750: PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8751: }
8752: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
8753: PetscObjectStateIncrease((PetscObject)mat);
8754: return 0;
8755: }
8757: /*@
8758: MatGetInertia - Gets the inertia from a factored matrix
8760: Collective on mat
8762: Input Parameter:
8763: . mat - the matrix
8765: Output Parameters:
8766: + nneg - number of negative eigenvalues
8767: . nzero - number of zero eigenvalues
8768: - npos - number of positive eigenvalues
8770: Level: advanced
8772: Note:
8773: Matrix must have been factored by `MatCholeskyFactor()`
8775: .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8776: @*/
8777: PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8778: {
8783: PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8784: return 0;
8785: }
8787: /* ----------------------------------------------------------------*/
8788: /*@C
8789: MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8791: Neighbor-wise Collective on mat
8793: Input Parameters:
8794: + mat - the factored matrix obtained with `MatGetFactor()`
8795: - b - the right-hand-side vectors
8797: Output Parameter:
8798: . x - the result vectors
8800: Note:
8801: The vectors b and x cannot be the same. I.e., one cannot
8802: call `MatSolves`(A,x,x).
8804: Level: developer
8806: .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8807: @*/
8808: PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
8809: {
8814: if (!mat->rmap->N && !mat->cmap->N) return 0;
8816: MatCheckPreallocated(mat, 1);
8817: PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0);
8818: PetscUseTypeMethod(mat, solves, b, x);
8819: PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0);
8820: return 0;
8821: }
8823: /*@
8824: MatIsSymmetric - Test whether a matrix is symmetric
8826: Collective on mat
8828: Input Parameters:
8829: + A - the matrix to test
8830: - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
8832: Output Parameters:
8833: . flg - the result
8835: Notes:
8836: For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8838: If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
8840: One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8841: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8843: Level: intermediate
8845: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
8846: `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8847: @*/
8848: PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
8849: {
8853: if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8854: else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8855: else {
8856: if (!A->ops->issymmetric) {
8857: MatType mattype;
8858: MatGetType(A, &mattype);
8859: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8860: }
8861: PetscUseTypeMethod(A, issymmetric, tol, flg);
8862: if (!tol) MatSetOption(A, MAT_SYMMETRIC, *flg);
8863: }
8864: return 0;
8865: }
8867: /*@
8868: MatIsHermitian - Test whether a matrix is Hermitian
8870: Collective on Mat
8872: Input Parameters:
8873: + A - the matrix to test
8874: - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
8876: Output Parameters:
8877: . flg - the result
8879: Level: intermediate
8881: Notes:
8882: For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8884: If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
8886: One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8887: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
8889: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8890: `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8891: @*/
8892: PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
8893: {
8897: if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8898: else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8899: else {
8900: if (!A->ops->ishermitian) {
8901: MatType mattype;
8902: MatGetType(A, &mattype);
8903: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8904: }
8905: PetscUseTypeMethod(A, ishermitian, tol, flg);
8906: if (!tol) MatSetOption(A, MAT_HERMITIAN, *flg);
8907: }
8908: return 0;
8909: }
8911: /*@
8912: MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
8914: Not Collective
8916: Input Parameter:
8917: . A - the matrix to check
8919: Output Parameters:
8920: + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
8921: - flg - the result (only valid if set is `PETSC_TRUE`)
8923: Level: advanced
8925: Notes:
8926: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
8927: if you want it explicitly checked
8929: One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8930: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8932: .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8933: @*/
8934: PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
8935: {
8939: if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8940: *set = PETSC_TRUE;
8941: *flg = PetscBool3ToBool(A->symmetric);
8942: } else {
8943: *set = PETSC_FALSE;
8944: }
8945: return 0;
8946: }
8948: /*@
8949: MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
8951: Not Collective
8953: Input Parameter:
8954: . A - the matrix to check
8956: Output Parameters:
8957: + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
8958: - flg - the result (only valid if set is `PETSC_TRUE`)
8960: Level: advanced
8962: Notes:
8963: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
8965: One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
8966: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
8968: .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8969: @*/
8970: PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
8971: {
8975: if (A->spd != PETSC_BOOL3_UNKNOWN) {
8976: *set = PETSC_TRUE;
8977: *flg = PetscBool3ToBool(A->spd);
8978: } else {
8979: *set = PETSC_FALSE;
8980: }
8981: return 0;
8982: }
8984: /*@
8985: MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
8987: Not Collective
8989: Input Parameter:
8990: . A - the matrix to check
8992: Output Parameters:
8993: + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
8994: - flg - the result (only valid if set is `PETSC_TRUE`)
8996: Level: advanced
8998: Notes:
8999: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9000: if you want it explicitly checked
9002: One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9003: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9005: .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9006: @*/
9007: PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9008: {
9012: if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9013: *set = PETSC_TRUE;
9014: *flg = PetscBool3ToBool(A->hermitian);
9015: } else {
9016: *set = PETSC_FALSE;
9017: }
9018: return 0;
9019: }
9021: /*@
9022: MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9024: Collective on Mat
9026: Input Parameter:
9027: . A - the matrix to test
9029: Output Parameters:
9030: . flg - the result
9032: Notes:
9033: If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9035: 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
9036: symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9038: Level: intermediate
9040: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9041: @*/
9042: PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9043: {
9046: if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9047: *flg = PetscBool3ToBool(A->structurally_symmetric);
9048: } else {
9049: PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9050: MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg);
9051: }
9052: return 0;
9053: }
9055: /*@
9056: MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9058: Not Collective
9060: Input Parameter:
9061: . A - the matrix to check
9063: Output Parameters:
9064: + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9065: - flg - the result (only valid if set is PETSC_TRUE)
9067: Level: advanced
9069: Notes:
9070: 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
9071: symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9073: Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9075: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9076: @*/
9077: PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9078: {
9082: if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9083: *set = PETSC_TRUE;
9084: *flg = PetscBool3ToBool(A->structurally_symmetric);
9085: } else {
9086: *set = PETSC_FALSE;
9087: }
9088: return 0;
9089: }
9091: /*@
9092: MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9093: to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9095: Not collective
9097: Input Parameter:
9098: . mat - the matrix
9100: Output Parameters:
9101: + nstash - the size of the stash
9102: . reallocs - the number of additional mallocs incurred.
9103: . bnstash - the size of the block stash
9104: - breallocs - the number of additional mallocs incurred.in the block stash
9106: Level: advanced
9108: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9109: @*/
9110: PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9111: {
9112: MatStashGetInfo_Private(&mat->stash, nstash, reallocs);
9113: MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs);
9114: return 0;
9115: }
9117: /*@C
9118: MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9119: parallel layout, `PetscLayout` for rows and columns
9121: Collective on mat
9123: Input Parameter:
9124: . mat - the matrix
9126: Output Parameters:
9127: + right - (optional) vector that the matrix can be multiplied against
9128: - left - (optional) vector that the matrix vector product can be stored in
9130: Notes:
9131: 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()`.
9133: These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9135: Level: advanced
9137: .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9138: @*/
9139: PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9140: {
9143: if (mat->ops->getvecs) {
9144: PetscUseTypeMethod(mat, getvecs, right, left);
9145: } else {
9146: PetscInt rbs, cbs;
9147: MatGetBlockSizes(mat, &rbs, &cbs);
9148: if (right) {
9150: VecCreate(PetscObjectComm((PetscObject)mat), right);
9151: VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE);
9152: VecSetBlockSize(*right, cbs);
9153: VecSetType(*right, mat->defaultvectype);
9154: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9155: if (mat->boundtocpu && mat->bindingpropagates) {
9156: VecSetBindingPropagates(*right, PETSC_TRUE);
9157: VecBindToCPU(*right, PETSC_TRUE);
9158: }
9159: #endif
9160: PetscLayoutReference(mat->cmap, &(*right)->map);
9161: }
9162: if (left) {
9164: VecCreate(PetscObjectComm((PetscObject)mat), left);
9165: VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE);
9166: VecSetBlockSize(*left, rbs);
9167: VecSetType(*left, mat->defaultvectype);
9168: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9169: if (mat->boundtocpu && mat->bindingpropagates) {
9170: VecSetBindingPropagates(*left, PETSC_TRUE);
9171: VecBindToCPU(*left, PETSC_TRUE);
9172: }
9173: #endif
9174: PetscLayoutReference(mat->rmap, &(*left)->map);
9175: }
9176: }
9177: return 0;
9178: }
9180: /*@C
9181: MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9182: with default values.
9184: Not Collective
9186: Input Parameters:
9187: . info - the `MatFactorInfo` data structure
9189: Notes:
9190: The solvers are generally used through the `KSP` and `PC` objects, for example
9191: `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9193: Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9195: Level: developer
9197: Developer Note:
9198: The Fortran interface is not autogenerated as the f90
9199: interface definition cannot be generated correctly [due to `MatFactorInfo`]
9201: .seealso: `MatGetFactor()`, `MatFactorInfo`
9202: @*/
9203: PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9204: {
9205: PetscMemzero(info, sizeof(MatFactorInfo));
9206: return 0;
9207: }
9209: /*@
9210: MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9212: Collective on mat
9214: Input Parameters:
9215: + mat - the factored matrix
9216: - is - the index set defining the Schur indices (0-based)
9218: Notes:
9219: Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9221: You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9223: This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9225: Level: advanced
9227: .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9228: `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9230: @*/
9231: PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9232: {
9233: PetscErrorCode (*f)(Mat, IS);
9241: PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f);
9243: MatDestroy(&mat->schur);
9244: (*f)(mat, is);
9246: return 0;
9247: }
9249: /*@
9250: MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9252: Logically Collective on mat
9254: Input Parameters:
9255: + F - the factored matrix obtained by calling `MatGetFactor()`
9256: . S - location where to return the Schur complement, can be NULL
9257: - status - the status of the Schur complement matrix, can be NULL
9259: Notes:
9260: You must call `MatFactorSetSchurIS()` before calling this routine.
9262: This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9264: The routine provides a copy of the Schur matrix stored within the solver data structures.
9265: The caller must destroy the object when it is no longer needed.
9266: If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9268: 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)
9270: See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9272: Developer Note:
9273: The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9274: matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9276: Level: advanced
9278: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9279: @*/
9280: PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9281: {
9285: if (S) {
9286: PetscErrorCode (*f)(Mat, Mat *);
9288: PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f);
9289: if (f) {
9290: (*f)(F, S);
9291: } else {
9292: MatDuplicate(F->schur, MAT_COPY_VALUES, S);
9293: }
9294: }
9295: if (status) *status = F->schur_status;
9296: return 0;
9297: }
9299: /*@
9300: MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9302: Logically Collective on mat
9304: Input Parameters:
9305: + F - the factored matrix obtained by calling `MatGetFactor()`
9306: . *S - location where to return the Schur complement, can be NULL
9307: - status - the status of the Schur complement matrix, can be NULL
9309: Notes:
9310: You must call `MatFactorSetSchurIS()` before calling this routine.
9312: Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9314: The routine returns a the Schur Complement stored within the data strutures of the solver.
9316: If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9318: The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9320: Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9322: See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9324: Level: advanced
9326: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9327: @*/
9328: PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9329: {
9333: if (S) *S = F->schur;
9334: if (status) *status = F->schur_status;
9335: return 0;
9336: }
9338: /*@
9339: MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9341: Logically Collective on mat
9343: Input Parameters:
9344: + F - the factored matrix obtained by calling `MatGetFactor()`
9345: . *S - location where the Schur complement is stored
9346: - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9348: Level: advanced
9350: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9351: @*/
9352: PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9353: {
9355: if (S) {
9357: *S = NULL;
9358: }
9359: F->schur_status = status;
9360: MatFactorUpdateSchurStatus_Private(F);
9361: return 0;
9362: }
9364: /*@
9365: MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9367: Logically Collective on mat
9369: Input Parameters:
9370: + F - the factored matrix obtained by calling `MatGetFactor()`
9371: . rhs - location where the right hand side of the Schur complement system is stored
9372: - sol - location where the solution of the Schur complement system has to be returned
9374: Notes:
9375: The sizes of the vectors should match the size of the Schur complement
9377: Must be called after `MatFactorSetSchurIS()`
9379: Level: advanced
9381: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9382: @*/
9383: PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9384: {
9393: MatFactorFactorizeSchurComplement(F);
9394: switch (F->schur_status) {
9395: case MAT_FACTOR_SCHUR_FACTORED:
9396: MatSolveTranspose(F->schur, rhs, sol);
9397: break;
9398: case MAT_FACTOR_SCHUR_INVERTED:
9399: MatMultTranspose(F->schur, rhs, sol);
9400: break;
9401: default:
9402: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9403: }
9404: return 0;
9405: }
9407: /*@
9408: MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9410: Logically Collective on mat
9412: Input Parameters:
9413: + F - the factored matrix obtained by calling `MatGetFactor()`
9414: . rhs - location where the right hand side of the Schur complement system is stored
9415: - sol - location where the solution of the Schur complement system has to be returned
9417: Notes:
9418: The sizes of the vectors should match the size of the Schur complement
9420: Must be called after `MatFactorSetSchurIS()`
9422: Level: advanced
9424: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9425: @*/
9426: PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9427: {
9436: MatFactorFactorizeSchurComplement(F);
9437: switch (F->schur_status) {
9438: case MAT_FACTOR_SCHUR_FACTORED:
9439: MatSolve(F->schur, rhs, sol);
9440: break;
9441: case MAT_FACTOR_SCHUR_INVERTED:
9442: MatMult(F->schur, rhs, sol);
9443: break;
9444: default:
9445: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9446: }
9447: return 0;
9448: }
9450: /*@
9451: MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9453: Logically Collective on F
9455: Input Parameters:
9456: . F - the factored matrix obtained by calling `MatGetFactor()`
9458: Notes:
9459: Must be called after `MatFactorSetSchurIS()`.
9461: Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9463: Level: advanced
9465: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9466: @*/
9467: PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9468: {
9471: if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) return 0;
9472: MatFactorFactorizeSchurComplement(F);
9473: MatFactorInvertSchurComplement_Private(F);
9474: F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9475: return 0;
9476: }
9478: /*@
9479: MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9481: Logically Collective on mat
9483: Input Parameters:
9484: . F - the factored matrix obtained by calling `MatGetFactor()`
9486: Note:
9487: Must be called after `MatFactorSetSchurIS()`
9489: Level: advanced
9491: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9492: @*/
9493: PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9494: {
9497: if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) return 0;
9498: MatFactorFactorizeSchurComplement_Private(F);
9499: F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9500: return 0;
9501: }
9503: /*@
9504: MatPtAP - Creates the matrix product C = P^T * A * P
9506: Neighbor-wise Collective on A
9508: Input Parameters:
9509: + A - the matrix
9510: . P - the projection matrix
9511: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9512: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9513: if the result is a dense matrix this is irrelevant
9515: Output Parameters:
9516: . C - the product matrix
9518: Notes:
9519: C will be created and must be destroyed by the user with `MatDestroy()`.
9521: An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9523: Developer Note:
9524: For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9526: Level: intermediate
9528: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9529: @*/
9530: PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9531: {
9532: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9535: if (scall == MAT_INITIAL_MATRIX) {
9536: MatProductCreate(A, P, NULL, C);
9537: MatProductSetType(*C, MATPRODUCT_PtAP);
9538: MatProductSetAlgorithm(*C, "default");
9539: MatProductSetFill(*C, fill);
9541: (*C)->product->api_user = PETSC_TRUE;
9542: MatProductSetFromOptions(*C);
9544: MatProductSymbolic(*C);
9545: } else { /* scall == MAT_REUSE_MATRIX */
9546: MatProductReplaceMats(A, P, NULL, *C);
9547: }
9549: MatProductNumeric(*C);
9550: (*C)->symmetric = A->symmetric;
9551: (*C)->spd = A->spd;
9552: return 0;
9553: }
9555: /*@
9556: MatRARt - Creates the matrix product C = R * A * R^T
9558: Neighbor-wise Collective on A
9560: Input Parameters:
9561: + A - the matrix
9562: . R - the projection matrix
9563: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9564: - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9565: if the result is a dense matrix this is irrelevant
9567: Output Parameters:
9568: . C - the product matrix
9570: Notes:
9571: C will be created and must be destroyed by the user with `MatDestroy()`.
9573: An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9575: This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9576: which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9577: parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9578: We recommend using MatPtAP().
9580: Level: intermediate
9582: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9583: @*/
9584: PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9585: {
9586: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9589: if (scall == MAT_INITIAL_MATRIX) {
9590: MatProductCreate(A, R, NULL, C);
9591: MatProductSetType(*C, MATPRODUCT_RARt);
9592: MatProductSetAlgorithm(*C, "default");
9593: MatProductSetFill(*C, fill);
9595: (*C)->product->api_user = PETSC_TRUE;
9596: MatProductSetFromOptions(*C);
9598: MatProductSymbolic(*C);
9599: } else { /* scall == MAT_REUSE_MATRIX */
9600: MatProductReplaceMats(A, R, NULL, *C);
9601: }
9603: MatProductNumeric(*C);
9604: if (A->symmetric == PETSC_BOOL3_TRUE) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9605: return 0;
9606: }
9608: static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9609: {
9612: if (scall == MAT_INITIAL_MATRIX) {
9613: PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]);
9614: MatProductCreate(A, B, NULL, C);
9615: MatProductSetType(*C, ptype);
9616: MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT);
9617: MatProductSetFill(*C, fill);
9619: (*C)->product->api_user = PETSC_TRUE;
9620: MatProductSetFromOptions(*C);
9621: MatProductSymbolic(*C);
9622: } else { /* scall == MAT_REUSE_MATRIX */
9623: Mat_Product *product = (*C)->product;
9624: PetscBool isdense;
9626: PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "");
9627: if (isdense && product && product->type != ptype) {
9628: MatProductClear(*C);
9629: product = NULL;
9630: }
9631: PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]);
9632: if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9633: if (isdense) {
9634: MatProductCreate_Private(A, B, NULL, *C);
9635: product = (*C)->product;
9636: product->fill = fill;
9637: product->api_user = PETSC_TRUE;
9638: product->clear = PETSC_TRUE;
9640: MatProductSetType(*C, ptype);
9641: MatProductSetFromOptions(*C);
9643: MatProductSymbolic(*C);
9644: } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9645: } else { /* user may change input matrices A or B when REUSE */
9646: MatProductReplaceMats(A, B, NULL, *C);
9647: }
9648: }
9649: MatProductNumeric(*C);
9650: return 0;
9651: }
9653: /*@
9654: MatMatMult - Performs matrix-matrix multiplication C=A*B.
9656: Neighbor-wise Collective on A
9658: Input Parameters:
9659: + A - the left matrix
9660: . B - the right matrix
9661: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9662: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9663: if the result is a dense matrix this is irrelevant
9665: Output Parameters:
9666: . C - the product matrix
9668: Notes:
9669: Unless scall is `MAT_REUSE_MATRIX` C will be created.
9671: `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
9672: call to this function with `MAT_INITIAL_MATRIX`.
9674: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9676: 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`,
9677: rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9679: Example of Usage:
9680: .vb
9681: MatProductCreate(A,B,NULL,&C);
9682: MatProductSetType(C,MATPRODUCT_AB);
9683: MatProductSymbolic(C);
9684: MatProductNumeric(C); // compute C=A * B
9685: MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9686: MatProductNumeric(C);
9687: MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9688: MatProductNumeric(C);
9689: .ve
9691: Level: intermediate
9693: .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9694: @*/
9695: PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9696: {
9697: MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C);
9698: return 0;
9699: }
9701: /*@
9702: MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9704: Neighbor-wise Collective on A
9706: Input Parameters:
9707: + A - the left matrix
9708: . B - the right matrix
9709: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9710: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9712: Output Parameters:
9713: . C - the product matrix
9715: Notes:
9716: C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9718: `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9720: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9721: actually needed.
9723: This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9724: and for pairs of `MATMPIDENSE` matrices.
9726: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
9728: Options Database Keys:
9729: . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9730: first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9731: the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9733: Level: intermediate
9735: .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9736: @*/
9737: PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9738: {
9739: MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C);
9740: if (A == B) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9741: return 0;
9742: }
9744: /*@
9745: MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
9747: Neighbor-wise Collective on A
9749: Input Parameters:
9750: + A - the left matrix
9751: . B - the right matrix
9752: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9753: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9755: Output Parameters:
9756: . C - the product matrix
9758: Notes:
9759: C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9761: `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9763: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
9765: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9766: actually needed.
9768: This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9769: which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices.
9771: Level: intermediate
9773: .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9774: @*/
9775: PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9776: {
9777: MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C);
9778: return 0;
9779: }
9781: /*@
9782: MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
9784: Neighbor-wise Collective on A
9786: Input Parameters:
9787: + A - the left matrix
9788: . B - the middle matrix
9789: . C - the right matrix
9790: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9791: - 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
9792: if the result is a dense matrix this is irrelevant
9794: Output Parameters:
9795: . D - the product matrix
9797: Notes:
9798: Unless scall is `MAT_REUSE_MATRIX` D will be created.
9800: `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9802: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
9804: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9805: actually needed.
9807: If you have many matrices with the same non-zero structure to multiply, you
9808: should use `MAT_REUSE_MATRIX` in all calls but the first
9810: Level: intermediate
9812: .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9813: @*/
9814: PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
9815: {
9816: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
9819: if (scall == MAT_INITIAL_MATRIX) {
9820: MatProductCreate(A, B, C, D);
9821: MatProductSetType(*D, MATPRODUCT_ABC);
9822: MatProductSetAlgorithm(*D, "default");
9823: MatProductSetFill(*D, fill);
9825: (*D)->product->api_user = PETSC_TRUE;
9826: MatProductSetFromOptions(*D);
9828: ((PetscObject)C)->type_name);
9829: MatProductSymbolic(*D);
9830: } else { /* user may change input matrices when REUSE */
9831: MatProductReplaceMats(A, B, C, *D);
9832: }
9833: MatProductNumeric(*D);
9834: return 0;
9835: }
9837: /*@
9838: MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9840: Collective on mat
9842: Input Parameters:
9843: + mat - the matrix
9844: . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9845: . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
9846: - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9848: Output Parameter:
9849: . matredundant - redundant matrix
9851: Notes:
9852: `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
9853: original matrix has not changed from that last call to MatCreateRedundantMatrix().
9855: This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9856: calling it.
9858: `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
9860: Level: advanced
9862: .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
9863: @*/
9864: PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
9865: {
9866: MPI_Comm comm;
9867: PetscMPIInt size;
9868: PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9869: Mat_Redundant *redund = NULL;
9870: PetscSubcomm psubcomm = NULL;
9871: MPI_Comm subcomm_in = subcomm;
9872: Mat *matseq;
9873: IS isrow, iscol;
9874: PetscBool newsubcomm = PETSC_FALSE;
9877: if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9880: }
9882: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
9883: if (size == 1 || nsubcomm == 1) {
9884: if (reuse == MAT_INITIAL_MATRIX) {
9885: MatDuplicate(mat, MAT_COPY_VALUES, matredundant);
9886: } else {
9888: MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN);
9889: }
9890: return 0;
9891: }
9895: MatCheckPreallocated(mat, 1);
9897: PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0);
9898: if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9899: /* create psubcomm, then get subcomm */
9900: PetscObjectGetComm((PetscObject)mat, &comm);
9901: MPI_Comm_size(comm, &size);
9904: PetscSubcommCreate(comm, &psubcomm);
9905: PetscSubcommSetNumber(psubcomm, nsubcomm);
9906: PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS);
9907: PetscSubcommSetFromOptions(psubcomm);
9908: PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL);
9909: newsubcomm = PETSC_TRUE;
9910: PetscSubcommDestroy(&psubcomm);
9911: }
9913: /* get isrow, iscol and a local sequential matrix matseq[0] */
9914: if (reuse == MAT_INITIAL_MATRIX) {
9915: mloc_sub = PETSC_DECIDE;
9916: nloc_sub = PETSC_DECIDE;
9917: if (bs < 1) {
9918: PetscSplitOwnership(subcomm, &mloc_sub, &M);
9919: PetscSplitOwnership(subcomm, &nloc_sub, &N);
9920: } else {
9921: PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M);
9922: PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N);
9923: }
9924: MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm);
9925: rstart = rend - mloc_sub;
9926: ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow);
9927: ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol);
9928: } else { /* reuse == MAT_REUSE_MATRIX */
9930: /* retrieve subcomm */
9931: PetscObjectGetComm((PetscObject)(*matredundant), &subcomm);
9932: redund = (*matredundant)->redundant;
9933: isrow = redund->isrow;
9934: iscol = redund->iscol;
9935: matseq = redund->matseq;
9936: }
9937: MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq);
9939: /* get matredundant over subcomm */
9940: if (reuse == MAT_INITIAL_MATRIX) {
9941: MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant);
9943: /* create a supporting struct and attach it to C for reuse */
9944: PetscNew(&redund);
9945: (*matredundant)->redundant = redund;
9946: redund->isrow = isrow;
9947: redund->iscol = iscol;
9948: redund->matseq = matseq;
9949: if (newsubcomm) {
9950: redund->subcomm = subcomm;
9951: } else {
9952: redund->subcomm = MPI_COMM_NULL;
9953: }
9954: } else {
9955: MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant);
9956: }
9957: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9958: if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
9959: MatBindToCPU(*matredundant, PETSC_TRUE);
9960: MatSetBindingPropagates(*matredundant, PETSC_TRUE);
9961: }
9962: #endif
9963: PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0);
9964: return 0;
9965: }
9967: /*@C
9968: MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
9969: a given `Mat`. Each submatrix can span multiple procs.
9971: Collective on mat
9973: Input Parameters:
9974: + mat - the matrix
9975: . subcomm - the subcommunicator obtained by MPI_Com_split(comm)
9976: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9978: Output Parameter:
9979: . subMat - 'parallel submatrices each spans a given subcomm
9981: Notes:
9982: The submatrix partition across processors is dictated by 'subComm' a
9983: communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
9984: is not restriced to be grouped with consecutive original ranks.
9986: Due the MPI_Comm_split() usage, the parallel layout of the submatrices
9987: map directly to the layout of the original matrix [wrt the local
9988: row,col partitioning]. So the original 'DiagonalMat' naturally maps
9989: into the 'DiagonalMat' of the subMat, hence it is used directly from
9990: the subMat. However the offDiagMat looses some columns - and this is
9991: reconstructed with `MatSetValues()`
9993: This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
9995: Level: advanced
9997: .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
9998: @*/
9999: PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10000: {
10001: PetscMPIInt commsize, subCommSize;
10003: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize);
10004: MPI_Comm_size(subComm, &subCommSize);
10008: PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10009: PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10010: PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10011: return 0;
10012: }
10014: /*@
10015: MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10017: Not Collective
10019: Input Parameters:
10020: + mat - matrix to extract local submatrix from
10021: . isrow - local row indices for submatrix
10022: - iscol - local column indices for submatrix
10024: Output Parameter:
10025: . submat - the submatrix
10027: Level: intermediate
10029: Notes:
10030: The submat should be returned with `MatRestoreLocalSubMatrix()`.
10032: Depending on the format of mat, the returned submat may not implement `MatMult()`. Its communicator may be
10033: the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.
10035: The submat always implements `MatSetValuesLocal()`. If isrow and iscol have the same block size, then
10036: `MatSetValuesBlockedLocal()` will also be implemented.
10038: The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10039: Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10041: .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10042: @*/
10043: PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10044: {
10052: if (mat->ops->getlocalsubmatrix) {
10053: PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10054: } else {
10055: MatCreateLocalRef(mat, isrow, iscol, submat);
10056: }
10057: return 0;
10058: }
10060: /*@
10061: MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10063: Not Collective
10065: Input Parameters:
10066: + mat - matrix to extract local submatrix from
10067: . isrow - local row indices for submatrix
10068: . iscol - local column indices for submatrix
10069: - submat - the submatrix
10071: Level: intermediate
10073: .seealso: `MatGetLocalSubMatrix()`
10074: @*/
10075: PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10076: {
10084: if (mat->ops->restorelocalsubmatrix) {
10085: PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10086: } else {
10087: MatDestroy(submat);
10088: }
10089: *submat = NULL;
10090: return 0;
10091: }
10093: /* --------------------------------------------------------*/
10094: /*@
10095: MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10097: Collective on mat
10099: Input Parameter:
10100: . mat - the matrix
10102: Output Parameter:
10103: . is - if any rows have zero diagonals this contains the list of them
10105: Level: developer
10107: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10108: @*/
10109: PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10110: {
10116: if (!mat->ops->findzerodiagonals) {
10117: Vec diag;
10118: const PetscScalar *a;
10119: PetscInt *rows;
10120: PetscInt rStart, rEnd, r, nrow = 0;
10122: MatCreateVecs(mat, &diag, NULL);
10123: MatGetDiagonal(mat, diag);
10124: MatGetOwnershipRange(mat, &rStart, &rEnd);
10125: VecGetArrayRead(diag, &a);
10126: for (r = 0; r < rEnd - rStart; ++r)
10127: if (a[r] == 0.0) ++nrow;
10128: PetscMalloc1(nrow, &rows);
10129: nrow = 0;
10130: for (r = 0; r < rEnd - rStart; ++r)
10131: if (a[r] == 0.0) rows[nrow++] = r + rStart;
10132: VecRestoreArrayRead(diag, &a);
10133: VecDestroy(&diag);
10134: ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is);
10135: } else {
10136: PetscUseTypeMethod(mat, findzerodiagonals, is);
10137: }
10138: return 0;
10139: }
10141: /*@
10142: MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10144: Collective on mat
10146: Input Parameter:
10147: . mat - the matrix
10149: Output Parameter:
10150: . is - contains the list of rows with off block diagonal entries
10152: Level: developer
10154: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10155: @*/
10156: PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10157: {
10163: PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10164: return 0;
10165: }
10167: /*@C
10168: MatInvertBlockDiagonal - Inverts the block diagonal entries.
10170: Collective on mat
10172: Input Parameters:
10173: . mat - the matrix
10175: Output Parameters:
10176: . values - the block inverses in column major order (FORTRAN-like)
10178: Notes:
10179: The size of the blocks is determined by the block size of the matrix.
10181: The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10183: The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10185: Fortran Note:
10186: This routine is not available from Fortran.
10188: Level: advanced
10190: .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10191: @*/
10192: PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10193: {
10197: PetscUseTypeMethod(mat, invertblockdiagonal, values);
10198: return 0;
10199: }
10201: /*@C
10202: MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10204: Collective on mat
10206: Input Parameters:
10207: + mat - the matrix
10208: . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10209: - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10211: Output Parameters:
10212: . values - the block inverses in column major order (FORTRAN-like)
10214: Notes:
10215: Use `MatInvertBlockDiagonal()` if all blocks have the same size
10217: The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10219: Fortran Note:
10220: This routine is not available from Fortran.
10222: Level: advanced
10224: .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10225: @*/
10226: PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10227: {
10231: PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10232: return 0;
10233: }
10235: /*@
10236: MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10238: Collective on Mat
10240: Input Parameters:
10241: + A - the matrix
10242: - C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set.
10244: Note:
10245: The blocksize of the matrix is used to determine the blocks on the diagonal of C
10247: Level: advanced
10249: .seealso: `MatInvertBlockDiagonal()`
10250: @*/
10251: PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10252: {
10253: const PetscScalar *vals;
10254: PetscInt *dnnz;
10255: PetscInt m, rstart, rend, bs, i, j;
10257: MatInvertBlockDiagonal(A, &vals);
10258: MatGetBlockSize(A, &bs);
10259: MatGetLocalSize(A, &m, NULL);
10260: MatSetLayouts(C, A->rmap, A->cmap);
10261: PetscMalloc1(m / bs, &dnnz);
10262: for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10263: MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL);
10264: PetscFree(dnnz);
10265: MatGetOwnershipRange(C, &rstart, &rend);
10266: MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE);
10267: for (i = rstart / bs; i < rend / bs; i++) MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES);
10268: MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY);
10269: MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY);
10270: MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE);
10271: return 0;
10272: }
10274: /*@C
10275: MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10276: via `MatTransposeColoringCreate()`.
10278: Collective on c
10280: Input Parameter:
10281: . c - coloring context
10283: Level: intermediate
10285: .seealso: `MatTransposeColoringCreate()`
10286: @*/
10287: PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10288: {
10289: MatTransposeColoring matcolor = *c;
10291: if (!matcolor) return 0;
10292: if (--((PetscObject)matcolor)->refct > 0) {
10293: matcolor = NULL;
10294: return 0;
10295: }
10297: PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow);
10298: PetscFree(matcolor->rows);
10299: PetscFree(matcolor->den2sp);
10300: PetscFree(matcolor->colorforcol);
10301: PetscFree(matcolor->columns);
10302: if (matcolor->brows > 0) PetscFree(matcolor->lstart);
10303: PetscHeaderDestroy(c);
10304: return 0;
10305: }
10307: /*@C
10308: MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10309: a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10310: `MatTransposeColoring` to sparse B.
10312: Collective on coloring
10314: Input Parameters:
10315: + B - sparse matrix B
10316: . Btdense - symbolic dense matrix B^T
10317: - coloring - coloring context created with `MatTransposeColoringCreate()`
10319: Output Parameter:
10320: . Btdense - dense matrix B^T
10322: Level: developer
10324: Note:
10325: These are used internally for some implementations of `MatRARt()`
10327: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10329: @*/
10330: PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10331: {
10336: (B->ops->transcoloringapplysptoden)(coloring, B, Btdense);
10337: return 0;
10338: }
10340: /*@C
10341: MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10342: a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10343: in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10344: Csp from Cden.
10346: Collective on matcoloring
10348: Input Parameters:
10349: + coloring - coloring context created with `MatTransposeColoringCreate()`
10350: - Cden - matrix product of a sparse matrix and a dense matrix Btdense
10352: Output Parameter:
10353: . Csp - sparse matrix
10355: Level: developer
10357: Note:
10358: These are used internally for some implementations of `MatRARt()`
10360: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10362: @*/
10363: PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10364: {
10369: (Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp);
10370: MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY);
10371: MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY);
10372: return 0;
10373: }
10375: /*@C
10376: MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10378: Collective on mat
10380: Input Parameters:
10381: + mat - the matrix product C
10382: - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10384: Output Parameter:
10385: . color - the new coloring context
10387: Level: intermediate
10389: .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10390: `MatTransColoringApplyDenToSp()`
10391: @*/
10392: PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10393: {
10394: MatTransposeColoring c;
10395: MPI_Comm comm;
10397: PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10398: PetscObjectGetComm((PetscObject)mat, &comm);
10399: PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL);
10401: c->ctype = iscoloring->ctype;
10402: if (mat->ops->transposecoloringcreate) {
10403: PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10404: } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10406: *color = c;
10407: PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10408: return 0;
10409: }
10411: /*@
10412: MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10413: matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10414: same, otherwise it will be larger
10416: Not Collective
10418: Input Parameter:
10419: . A - the matrix
10421: Output Parameter:
10422: . state - the current state
10424: Notes:
10425: You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10426: different matrices
10428: Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10430: Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10432: Level: intermediate
10434: .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10435: @*/
10436: PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10437: {
10439: *state = mat->nonzerostate;
10440: return 0;
10441: }
10443: /*@
10444: MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10445: matrices from each processor
10447: Collective
10449: Input Parameters:
10450: + comm - the communicators the parallel matrix will live on
10451: . seqmat - the input sequential matrices
10452: . n - number of local columns (or `PETSC_DECIDE`)
10453: - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10455: Output Parameter:
10456: . mpimat - the parallel matrix generated
10458: Level: developer
10460: Note:
10461: The number of columns of the matrix in EACH processor MUST be the same.
10463: .seealso: `Mat`
10464: @*/
10465: PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10466: {
10467: PetscMPIInt size;
10469: MPI_Comm_size(comm, &size);
10470: if (size == 1) {
10471: if (reuse == MAT_INITIAL_MATRIX) {
10472: MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat);
10473: } else {
10474: MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN);
10475: }
10476: return 0;
10477: }
10481: PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0);
10482: (*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat);
10483: PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0);
10484: return 0;
10485: }
10487: /*@
10488: MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10490: Collective on A
10492: Input Parameters:
10493: + A - the matrix to create subdomains from
10494: - N - requested number of subdomains
10496: Output Parameters:
10497: + n - number of subdomains resulting on this rank
10498: - iss - `IS` list with indices of subdomains on this rank
10500: Level: advanced
10502: Note:
10503: The number of subdomains must be smaller than the communicator size
10505: .seealso: `Mat`, `IS`
10506: @*/
10507: PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10508: {
10509: MPI_Comm comm, subcomm;
10510: PetscMPIInt size, rank, color;
10511: PetscInt rstart, rend, k;
10513: PetscObjectGetComm((PetscObject)A, &comm);
10514: MPI_Comm_size(comm, &size);
10515: MPI_Comm_rank(comm, &rank);
10517: *n = 1;
10518: k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10519: color = rank / k;
10520: MPI_Comm_split(comm, color, rank, &subcomm);
10521: PetscMalloc1(1, iss);
10522: MatGetOwnershipRange(A, &rstart, &rend);
10523: ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]);
10524: MPI_Comm_free(&subcomm);
10525: return 0;
10526: }
10528: /*@
10529: MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10531: If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10532: If they are not the same, uses `MatMatMatMult()`.
10534: Once the coarse grid problem is constructed, correct for interpolation operators
10535: that are not of full rank, which can legitimately happen in the case of non-nested
10536: geometric multigrid.
10538: Input Parameters:
10539: + restrct - restriction operator
10540: . dA - fine grid matrix
10541: . interpolate - interpolation operator
10542: . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10543: - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10545: Output Parameters:
10546: . A - the Galerkin coarse matrix
10548: Options Database Key:
10549: . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10551: Level: developer
10553: .seealso: `MatPtAP()`, `MatMatMatMult()`
10554: @*/
10555: PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10556: {
10557: IS zerorows;
10558: Vec diag;
10561: /* Construct the coarse grid matrix */
10562: if (interpolate == restrct) {
10563: MatPtAP(dA, interpolate, reuse, fill, A);
10564: } else {
10565: MatMatMatMult(restrct, dA, interpolate, reuse, fill, A);
10566: }
10568: /* If the interpolation matrix is not of full rank, A will have zero rows.
10569: This can legitimately happen in the case of non-nested geometric multigrid.
10570: In that event, we set the rows of the matrix to the rows of the identity,
10571: ignoring the equations (as the RHS will also be zero). */
10573: MatFindZeroRows(*A, &zerorows);
10575: if (zerorows != NULL) { /* if there are any zero rows */
10576: MatCreateVecs(*A, &diag, NULL);
10577: MatGetDiagonal(*A, diag);
10578: VecISSet(diag, zerorows, 1.0);
10579: MatDiagonalSet(*A, diag, INSERT_VALUES);
10580: VecDestroy(&diag);
10581: ISDestroy(&zerorows);
10582: }
10583: return 0;
10584: }
10586: /*@C
10587: MatSetOperation - Allows user to set a matrix operation for any matrix type
10589: Logically Collective on mat
10591: Input Parameters:
10592: + mat - the matrix
10593: . op - the name of the operation
10594: - f - the function that provides the operation
10596: Level: developer
10598: Usage:
10599: $ extern PetscErrorCode usermult(Mat,Vec,Vec);
10600: $ MatCreateXXX(comm,...&A;
10601: $ MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult;
10603: Notes:
10604: See the file include/petscmat.h for a complete list of matrix
10605: operations, which all have the form MATOP_<OPERATION>, where
10606: <OPERATION> is the name (in all capital letters) of the
10607: user interface routine (e.g., MatMult() -> MATOP_MULT).
10609: All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10610: sequence as the usual matrix interface routines, since they
10611: are intended to be accessed via the usual matrix interface
10612: routines, e.g.,
10613: $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10615: In particular each function MUST return an error code of 0 on success and
10616: nonzero on failure.
10618: This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10620: .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10621: @*/
10622: PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10623: {
10625: if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10626: (((void (**)(void))mat->ops)[op]) = f;
10627: return 0;
10628: }
10630: /*@C
10631: MatGetOperation - Gets a matrix operation for any matrix type.
10633: Not Collective
10635: Input Parameters:
10636: + mat - the matrix
10637: - op - the name of the operation
10639: Output Parameter:
10640: . f - the function that provides the operation
10642: Level: developer
10644: Usage:
10645: $ PetscErrorCode (*usermult)(Mat,Vec,Vec);
10646: $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10648: Notes:
10649: See the file include/petscmat.h for a complete list of matrix
10650: operations, which all have the form MATOP_<OPERATION>, where
10651: <OPERATION> is the name (in all capital letters) of the
10652: user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10654: This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10656: .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10657: @*/
10658: PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10659: {
10661: *f = (((void (**)(void))mat->ops)[op]);
10662: return 0;
10663: }
10665: /*@
10666: MatHasOperation - Determines whether the given matrix supports the particular operation.
10668: Not Collective
10670: Input Parameters:
10671: + mat - the matrix
10672: - op - the operation, for example, `MATOP_GET_DIAGONAL`
10674: Output Parameter:
10675: . has - either `PETSC_TRUE` or `PETSC_FALSE`
10677: Level: advanced
10679: Note:
10680: See the file include/petscmat.h for a complete list of matrix
10681: operations, which all have the form MATOP_<OPERATION>, where
10682: <OPERATION> is the name (in all capital letters) of the
10683: user-level routine. E.g., `MatNorm()` -> `MATOP_NORM`.
10685: .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10686: @*/
10687: PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10688: {
10691: if (mat->ops->hasoperation) {
10692: PetscUseTypeMethod(mat, hasoperation, op, has);
10693: } else {
10694: if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10695: else {
10696: *has = PETSC_FALSE;
10697: if (op == MATOP_CREATE_SUBMATRIX) {
10698: PetscMPIInt size;
10700: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
10701: if (size == 1) MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has);
10702: }
10703: }
10704: }
10705: return 0;
10706: }
10708: /*@
10709: MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
10711: Collective on mat
10713: Input Parameters:
10714: . mat - the matrix
10716: Output Parameter:
10717: . cong - either `PETSC_TRUE` or `PETSC_FALSE`
10719: Level: beginner
10721: .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10722: @*/
10723: PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10724: {
10728: if (!mat->rmap || !mat->cmap) {
10729: *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10730: return 0;
10731: }
10732: if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10733: PetscLayoutSetUp(mat->rmap);
10734: PetscLayoutSetUp(mat->cmap);
10735: PetscLayoutCompare(mat->rmap, mat->cmap, cong);
10736: if (*cong) mat->congruentlayouts = 1;
10737: else mat->congruentlayouts = 0;
10738: } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10739: return 0;
10740: }
10742: PetscErrorCode MatSetInf(Mat A)
10743: {
10744: PetscUseTypeMethod(A, setinf);
10745: return 0;
10746: }
10748: /*C
10749: 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
10750: and possibly removes small values from the graph structure.
10752: Collective on mat
10754: Input Parameters:
10755: + A - the matrix
10756: . sym - `PETSC_TRUE` indicates that the graph should be symmetrized
10757: . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
10758: - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
10760: Output Parameter:
10761: . graph - the resulting graph
10763: Level: advanced
10765: .seealso: `MatCreate()`, `PCGAMG`
10766: */
10767: PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
10768: {
10772: PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
10773: return 0;
10774: }