Actual source code: matrix.c
1: /*
2: This is where the abstract matrix operations are defined
3: Portions of this code are under:
4: Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5: */
7: #include <petsc/private/matimpl.h>
8: #include <petsc/private/isimpl.h>
9: #include <petsc/private/vecimpl.h>
11: /* Logging support */
12: PetscClassId MAT_CLASSID;
13: PetscClassId MAT_COLORING_CLASSID;
14: PetscClassId MAT_FDCOLORING_CLASSID;
15: PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
17: PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
18: PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19: PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20: PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21: PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22: PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23: PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24: PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25: PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26: PetscLogEvent MAT_TransposeColoringCreate;
27: PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28: PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29: PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30: PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31: PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32: PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33: PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34: PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35: PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
36: PetscLogEvent MAT_GetMultiProcBlock;
37: PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
38: PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
39: PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
40: PetscLogEvent MAT_SetValuesBatch;
41: PetscLogEvent MAT_ViennaCLCopyToGPU;
42: PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43: PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44: PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45: PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46: PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
48: const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
50: /*@
51: MatSetRandom - Sets all components of a matrix to random numbers.
53: Logically Collective
55: Input Parameters:
56: + x - the matrix
57: - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58: it will create one internally.
60: Output Parameter:
61: . x - the matrix
63: Example of Usage:
64: .vb
65: PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
66: MatSetRandom(x,rctx);
67: PetscRandomDestroy(rctx);
68: .ve
70: Level: intermediate
72: Note:
73: For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
74: for sparse matrices that already have locations it fills the locations with random numbers. It generates an error if used on sparse matrices that have
75: not been preallocated.
77: .seealso: `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
78: @*/
79: PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
80: {
81: PetscRandom randObj = NULL;
86: MatCheckPreallocated(x, 1);
88: if (!rctx) {
89: MPI_Comm comm;
90: PetscObjectGetComm((PetscObject)x, &comm);
91: PetscRandomCreate(comm, &randObj);
92: PetscRandomSetType(randObj, x->defaultrandtype);
93: PetscRandomSetFromOptions(randObj);
94: rctx = randObj;
95: }
96: PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0);
97: PetscUseTypeMethod(x, setrandom, rctx);
98: PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0);
100: MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY);
101: MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY);
102: PetscRandomDestroy(&randObj);
103: return 0;
104: }
106: /*@
107: MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
109: Logically Collective
111: Input Parameter:
112: . mat - the factored matrix
114: Output Parameters:
115: + pivot - the pivot value computed
116: - row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
117: the share the matrix
119: Level: advanced
121: Notes:
122: This routine does not work for factorizations done with external packages.
124: This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
126: This can be called on non-factored matrices that come from, for example, matrices used in SOR.
128: .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
129: `MAT_FACTOR_NUMERIC_ZEROPIVOT`
130: @*/
131: PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
132: {
136: *pivot = mat->factorerror_zeropivot_value;
137: *row = mat->factorerror_zeropivot_row;
138: return 0;
139: }
141: /*@
142: MatFactorGetError - gets the error code from a factorization
144: Logically Collective
146: Input Parameters:
147: . mat - the factored matrix
149: Output Parameter:
150: . err - the error code
152: Level: advanced
154: Note:
155: This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
157: .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
158: `MatFactorError`
159: @*/
160: PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
161: {
164: *err = mat->factorerrortype;
165: return 0;
166: }
168: /*@
169: MatFactorClearError - clears the error code in a factorization
171: Logically Collective
173: Input Parameter:
174: . mat - the factored matrix
176: Level: developer
178: Note:
179: This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
181: .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
182: `MatGetErrorCode()`, `MatFactorError`
183: @*/
184: PetscErrorCode MatFactorClearError(Mat mat)
185: {
187: mat->factorerrortype = MAT_FACTOR_NOERROR;
188: mat->factorerror_zeropivot_value = 0.0;
189: mat->factorerror_zeropivot_row = 0;
190: return 0;
191: }
193: PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
194: {
195: Vec r, l;
196: const PetscScalar *al;
197: PetscInt i, nz, gnz, N, n;
199: MatCreateVecs(mat, &r, &l);
200: if (!cols) { /* nonzero rows */
201: MatGetSize(mat, &N, NULL);
202: MatGetLocalSize(mat, &n, NULL);
203: VecSet(l, 0.0);
204: VecSetRandom(r, NULL);
205: MatMult(mat, r, l);
206: VecGetArrayRead(l, &al);
207: } else { /* nonzero columns */
208: MatGetSize(mat, NULL, &N);
209: MatGetLocalSize(mat, NULL, &n);
210: VecSet(r, 0.0);
211: VecSetRandom(l, NULL);
212: MatMultTranspose(mat, l, r);
213: VecGetArrayRead(r, &al);
214: }
215: if (tol <= 0.0) {
216: for (i = 0, nz = 0; i < n; i++)
217: if (al[i] != 0.0) nz++;
218: } else {
219: for (i = 0, nz = 0; i < n; i++)
220: if (PetscAbsScalar(al[i]) > tol) nz++;
221: }
222: MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
223: if (gnz != N) {
224: PetscInt *nzr;
225: PetscMalloc1(nz, &nzr);
226: if (nz) {
227: if (tol < 0) {
228: for (i = 0, nz = 0; i < n; i++)
229: if (al[i] != 0.0) nzr[nz++] = i;
230: } else {
231: for (i = 0, nz = 0; i < n; i++)
232: if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
233: }
234: }
235: ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero);
236: } else *nonzero = NULL;
237: if (!cols) { /* nonzero rows */
238: VecRestoreArrayRead(l, &al);
239: } else {
240: VecRestoreArrayRead(r, &al);
241: }
242: VecDestroy(&l);
243: VecDestroy(&r);
244: return 0;
245: }
247: /*@
248: MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
250: Input Parameter:
251: . A - the matrix
253: Output Parameter:
254: . keptrows - the rows that are not completely zero
256: Level: intermediate
258: Note:
259: `keptrows` is set to `NULL` if all rows are nonzero.
261: .seealso: `Mat`, `MatFindZeroRows()`
262: @*/
263: PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
264: {
270: if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
271: else MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows);
272: return 0;
273: }
275: /*@
276: MatFindZeroRows - Locate all rows that are completely zero in the matrix
278: Input Parameter:
279: . A - the matrix
281: Output Parameter:
282: . zerorows - the rows that are completely zero
284: Level: intermediate
286: Note:
287: `zerorows` is set to `NULL` if no rows are zero.
289: .seealso: `Mat`, `MatFindNonzeroRows()`
290: @*/
291: PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
292: {
293: IS keptrows;
294: PetscInt m, n;
299: MatFindNonzeroRows(mat, &keptrows);
300: /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
301: In keeping with this convention, we set zerorows to NULL if there are no zero
302: rows. */
303: if (keptrows == NULL) {
304: *zerorows = NULL;
305: } else {
306: MatGetOwnershipRange(mat, &m, &n);
307: ISComplement(keptrows, m, n, zerorows);
308: ISDestroy(&keptrows);
309: }
310: return 0;
311: }
313: /*@
314: MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
316: Not Collective
318: Input Parameters:
319: . A - the matrix
321: Output Parameters:
322: . a - the diagonal part (which is a SEQUENTIAL matrix)
324: Level: advanced
326: Notes:
327: See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
329: Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
331: .seealso: `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
332: @*/
333: PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
334: {
339: if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
340: else {
341: PetscMPIInt size;
343: MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);
345: *a = A;
346: }
347: return 0;
348: }
350: /*@
351: MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
353: Collective
355: Input Parameters:
356: . mat - the matrix
358: Output Parameter:
359: . trace - the sum of the diagonal entries
361: Level: advanced
363: .seealso: `Mat`
364: @*/
365: PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
366: {
367: Vec diag;
371: MatCreateVecs(mat, &diag, NULL);
372: MatGetDiagonal(mat, diag);
373: VecSum(diag, trace);
374: VecDestroy(&diag);
375: return 0;
376: }
378: /*@
379: MatRealPart - Zeros out the imaginary part of the matrix
381: Logically Collective
383: Input Parameters:
384: . mat - the matrix
386: Level: advanced
388: .seealso: `Mat`, `MatImaginaryPart()`
389: @*/
390: PetscErrorCode MatRealPart(Mat mat)
391: {
396: MatCheckPreallocated(mat, 1);
397: PetscUseTypeMethod(mat, realpart);
398: return 0;
399: }
401: /*@C
402: MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
404: Collective
406: Input Parameter:
407: . mat - the matrix
409: Output Parameters:
410: + nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
411: - ghosts - the global indices of the ghost points
413: Level: advanced
415: Note:
416: `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
418: .seealso: `Mat`, `VecCreateGhost()`
419: @*/
420: PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
421: {
426: if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
427: else {
428: if (nghosts) *nghosts = 0;
429: if (ghosts) *ghosts = NULL;
430: }
431: return 0;
432: }
434: /*@
435: MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
437: Logically Collective
439: Input Parameters:
440: . mat - the matrix
442: Level: advanced
444: .seealso: `Mat`, `MatRealPart()`
445: @*/
446: PetscErrorCode MatImaginaryPart(Mat mat)
447: {
452: MatCheckPreallocated(mat, 1);
453: PetscUseTypeMethod(mat, imaginarypart);
454: return 0;
455: }
457: /*@
458: MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
460: Not Collective
462: Input Parameter:
463: . mat - the matrix
465: Output Parameters:
466: + missing - is any diagonal missing
467: - dd - first diagonal entry that is missing (optional) on this process
469: Level: advanced
471: .seealso: `Mat`
472: @*/
473: PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
474: {
480: PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
481: return 0;
482: }
484: /*@C
485: MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()`
486: for each row that you get to ensure that your application does
487: not bleed memory.
489: Not Collective
491: Input Parameters:
492: + mat - the matrix
493: - row - the row to get
495: Output Parameters:
496: + ncols - if not `NULL`, the number of nonzeros in the row
497: . cols - if not `NULL`, the column numbers
498: - vals - if not `NULL`, the values
500: Level: advanced
502: Notes:
503: This routine is provided for people who need to have direct access
504: to the structure of a matrix. We hope that we provide enough
505: high-level matrix routines that few users will need it.
507: `MatGetRow()` always returns 0-based column indices, regardless of
508: whether the internal representation is 0-based (default) or 1-based.
510: For better efficiency, set cols and/or vals to `NULL` if you do
511: not wish to extract these quantities.
513: The user can only examine the values extracted with `MatGetRow()`;
514: the values cannot be altered. To change the matrix entries, one
515: must use `MatSetValues()`.
517: You can only have one call to `MatGetRow()` outstanding for a particular
518: matrix at a time, per processor. `MatGetRow()` can only obtain rows
519: associated with the given processor, it cannot get rows from the
520: other processors; for that we suggest using `MatCreateSubMatrices()`, then
521: MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
522: is in the global number of rows.
524: Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
526: Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
528: Fortran Note:
529: The calling sequence is
530: .vb
531: MatGetRow(matrix,row,ncols,cols,values,ierr)
532: Mat matrix (input)
533: integer row (input)
534: integer ncols (output)
535: integer cols(maxcols) (output)
536: double precision (or double complex) values(maxcols) output
537: .ve
538: where maxcols >= maximum nonzeros in any row of the matrix.
540: Caution:
541: Do not try to change the contents of the output arrays (cols and vals).
542: In some cases, this may corrupt the matrix.
544: .seealso: `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
545: @*/
546: PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
547: {
548: PetscInt incols;
554: MatCheckPreallocated(mat, 1);
556: PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0);
557: (*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
558: if (ncols) *ncols = incols;
559: PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0);
560: return 0;
561: }
563: /*@
564: MatConjugate - replaces the matrix values with their complex conjugates
566: Logically Collective
568: Input Parameters:
569: . mat - the matrix
571: Level: advanced
573: .seealso: `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
574: @*/
575: PetscErrorCode MatConjugate(Mat mat)
576: {
579: if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
580: PetscUseTypeMethod(mat, conjugate);
581: PetscObjectStateIncrease((PetscObject)mat);
582: }
583: return 0;
584: }
586: /*@C
587: MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
589: Not Collective
591: Input Parameters:
592: + mat - the matrix
593: . row - the row to get
594: . ncols, cols - the number of nonzeros and their columns
595: - vals - if nonzero the column values
597: Level: advanced
599: Notes:
600: This routine should be called after you have finished examining the entries.
602: This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
603: us of the array after it has been restored. If you pass `NULL`, it will
604: not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
606: Fortran Notes:
607: The calling sequence is
608: .vb
609: MatRestoreRow(matrix,row,ncols,cols,values,ierr)
610: Mat matrix (input)
611: integer row (input)
612: integer ncols (output)
613: integer cols(maxcols) (output)
614: double precision (or double complex) values(maxcols) output
615: .ve
616: Where maxcols >= maximum nonzeros in any row of the matrix.
618: In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
619: before another call to `MatGetRow()` can be made.
621: .seealso: `Mat`, `MatGetRow()`
622: @*/
623: PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
624: {
628: if (!mat->ops->restorerow) return 0;
629: (*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
630: if (ncols) *ncols = 0;
631: if (cols) *cols = NULL;
632: if (vals) *vals = NULL;
633: return 0;
634: }
636: /*@
637: MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
638: You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
640: Not Collective
642: Input Parameters:
643: . mat - the matrix
645: Level: advanced
647: Note:
648: 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.
650: .seealso: `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
651: @*/
652: PetscErrorCode MatGetRowUpperTriangular(Mat mat)
653: {
658: MatCheckPreallocated(mat, 1);
659: if (!mat->ops->getrowuppertriangular) return 0;
660: PetscUseTypeMethod(mat, getrowuppertriangular);
661: return 0;
662: }
664: /*@
665: MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
667: Not Collective
669: Input Parameters:
670: . mat - the matrix
672: Level: advanced
674: Note:
675: This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
677: .seealso: `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
678: @*/
679: PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
680: {
685: MatCheckPreallocated(mat, 1);
686: if (!mat->ops->restorerowuppertriangular) return 0;
687: PetscUseTypeMethod(mat, restorerowuppertriangular);
688: return 0;
689: }
691: /*@C
692: MatSetOptionsPrefix - Sets the prefix used for searching for all
693: `Mat` options in the database.
695: Logically Collective
697: Input Parameters:
698: + A - the matrix
699: - prefix - the prefix to prepend to all option names
701: Level: advanced
703: Notes:
704: A hyphen (-) must NOT be given at the beginning of the prefix name.
705: The first character of all runtime options is AUTOMATICALLY the hyphen.
707: This is NOT used for options for the factorization of the matrix. Normally the
708: prefix is automatically passed in from the PC calling the factorization. To set
709: it directly use `MatSetOptionsPrefixFactor()`
711: .seealso: `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
712: @*/
713: PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
714: {
716: PetscObjectSetOptionsPrefix((PetscObject)A, prefix);
717: return 0;
718: }
720: /*@C
721: MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
722: for matrices created with `MatGetFactor()`
724: Logically Collective
726: Input Parameters:
727: + A - the matrix
728: - prefix - the prefix to prepend to all option names for the factored matrix
730: Level: developer
732: Notes:
733: A hyphen (-) must NOT be given at the beginning of the prefix name.
734: The first character of all runtime options is AUTOMATICALLY the hyphen.
736: Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
737: it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()`
739: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
740: @*/
741: PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
742: {
744: if (prefix) {
747: if (prefix != A->factorprefix) {
748: PetscFree(A->factorprefix);
749: PetscStrallocpy(prefix, &A->factorprefix);
750: }
751: } else PetscFree(A->factorprefix);
752: return 0;
753: }
755: /*@C
756: MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
757: for matrices created with `MatGetFactor()`
759: Logically Collective
761: Input Parameters:
762: + A - the matrix
763: - prefix - the prefix to prepend to all option names for the factored matrix
765: Level: developer
767: Notes:
768: A hyphen (-) must NOT be given at the beginning of the prefix name.
769: The first character of all runtime options is AUTOMATICALLY the hyphen.
771: Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
772: it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()`
774: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
775: `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
776: `MatSetOptionsPrefix()`
777: @*/
778: PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
779: {
780: char *buf = A->factorprefix;
781: size_t len1, len2;
784: if (!prefix) return 0;
785: if (!buf) {
786: MatSetOptionsPrefixFactor(A, prefix);
787: return 0;
788: }
791: PetscStrlen(prefix, &len1);
792: PetscStrlen(buf, &len2);
793: PetscMalloc1(1 + len1 + len2, &A->factorprefix);
794: PetscStrcpy(A->factorprefix, buf);
795: PetscStrcat(A->factorprefix, prefix);
796: PetscFree(buf);
797: return 0;
798: }
800: /*@C
801: MatAppendOptionsPrefix - Appends to the prefix used for searching for all
802: matrix options in the database.
804: Logically Collective
806: Input Parameters:
807: + A - the matrix
808: - prefix - the prefix to prepend to all option names
810: Level: advanced
812: Note:
813: A hyphen (-) must NOT be given at the beginning of the prefix name.
814: The first character of all runtime options is AUTOMATICALLY the hyphen.
816: .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
817: @*/
818: PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
819: {
821: PetscObjectAppendOptionsPrefix((PetscObject)A, prefix);
822: return 0;
823: }
825: /*@C
826: MatGetOptionsPrefix - Gets the prefix used for searching for all
827: matrix options in the database.
829: Not Collective
831: Input Parameter:
832: . A - the matrix
834: Output Parameter:
835: . prefix - pointer to the prefix string used
837: Level: advanced
839: Fortran Note:
840: On the fortran side, the user should pass in a string `prefix` of
841: sufficient length to hold the prefix.
843: .seealso: `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
844: @*/
845: PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
846: {
849: PetscObjectGetOptionsPrefix((PetscObject)A, prefix);
850: return 0;
851: }
853: /*@
854: MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
856: Collective
858: Input Parameters:
859: . A - the matrix
861: Level: beginner
863: Notes:
864: The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
866: Users can reset the preallocation to access the original memory.
868: Currently only supported for `MATMPIAIJ` and `MATSEQAIJ` matrices.
870: .seealso: `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
871: @*/
872: PetscErrorCode MatResetPreallocation(Mat A)
873: {
876: PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
877: return 0;
878: }
880: /*@
881: MatSetUp - Sets up the internal matrix data structures for later use.
883: Collective
885: Input Parameters:
886: . A - the matrix
888: Level: intermediate
890: Notes:
891: If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
893: If a suitable preallocation routine is used, this function does not need to be called.
895: See the Performance chapter of the PETSc users manual for how to preallocate matrices
897: This routine is called internally by other matrix functions when needed so rarely needs to be called by users
899: .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
900: @*/
901: PetscErrorCode MatSetUp(Mat A)
902: {
904: if (!((PetscObject)A)->type_name) {
905: PetscMPIInt size;
907: MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);
908: MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ);
909: }
910: if (!A->preallocated && A->ops->setup) {
911: PetscInfo(A, "Warning not preallocating matrix storage\n");
912: PetscUseTypeMethod(A, setup);
913: }
914: PetscLayoutSetUp(A->rmap);
915: PetscLayoutSetUp(A->cmap);
916: A->preallocated = PETSC_TRUE;
917: return 0;
918: }
920: #if defined(PETSC_HAVE_SAWS)
921: #include <petscviewersaws.h>
922: #endif
924: /*@C
925: MatViewFromOptions - View properties of the matrix from the options database
927: Collective
929: Input Parameters:
930: + A - the matrix
931: . obj - optional additional object that provides the options prefix to use
932: - name - command line option
934: Options Database Key:
935: . -mat_view [viewertype]:... - the viewer and its options
937: Level: intermediate
939: Notes:
940: .vb
941: If no value is provided ascii:stdout is used
942: ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
943: for example ascii::ascii_info prints just the information about the object not all details
944: unless :append is given filename opens in write mode, overwriting what was already there
945: binary[:[filename][:[format][:append]]] defaults to the file binaryoutput
946: draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x
947: socket[:port] defaults to the standard output port
948: saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs)
949: .ve
951: .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
952: @*/
953: PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
954: {
956: PetscObjectViewFromOptions((PetscObject)A, obj, name);
957: return 0;
958: }
960: /*@C
961: MatView - display information about a matrix in a variety ways
963: Collective
965: Input Parameters:
966: + mat - the matrix
967: - viewer - visualization context
969: Notes:
970: The available visualization contexts include
971: + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
972: . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
973: . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
974: - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
976: The user can open alternative visualization contexts with
977: + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
978: . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
979: specified file; corresponding input uses MatLoad()
980: . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
981: an X window display
982: - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
983: Currently only the sequential dense and AIJ
984: matrix types support the Socket viewer.
986: The user can call `PetscViewerPushFormat()` to specify the output
987: format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
988: `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include
989: + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
990: . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
991: . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
992: . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
993: format common among all matrix types
994: . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
995: format (which is in many cases the same as the default)
996: . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
997: size and structure (not the matrix entries)
998: - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
999: the matrix structure
1001: Options Database Keys:
1002: + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1003: . -mat_view ::ascii_info_detail - Prints more detailed info
1004: . -mat_view - Prints matrix in ASCII format
1005: . -mat_view ::ascii_matlab - Prints matrix in Matlab format
1006: . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1007: . -display <name> - Sets display name (default is host)
1008: . -draw_pause <sec> - Sets number of seconds to pause after display
1009: . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1010: . -viewer_socket_machine <machine> -
1011: . -viewer_socket_port <port> -
1012: . -mat_view binary - save matrix to file in binary format
1013: - -viewer_binary_filename <name> -
1015: Level: beginner
1017: Notes:
1018: The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1019: the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1021: In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1023: See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1024: viewer is used.
1026: See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1027: viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1029: One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1030: and then use the following mouse functions.
1031: .vb
1032: left mouse: zoom in
1033: middle mouse: zoom out
1034: right mouse: continue with the simulation
1035: .ve
1037: .seealso: `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1038: `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1039: @*/
1040: PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1041: {
1042: PetscInt rows, cols, rbs, cbs;
1043: PetscBool isascii, isstring, issaws;
1044: PetscViewerFormat format;
1045: PetscMPIInt size;
1049: if (!viewer) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer);
1053: PetscViewerGetFormat(viewer, &format);
1054: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
1055: if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) return 0;
1057: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring);
1058: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
1059: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws);
1062: PetscLogEventBegin(MAT_View, mat, viewer, 0, 0);
1063: if (isascii) {
1064: if (!mat->preallocated) {
1065: PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n");
1066: return 0;
1067: }
1068: if (!mat->assembled) {
1069: PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n");
1070: return 0;
1071: }
1072: PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer);
1073: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1074: MatNullSpace nullsp, transnullsp;
1076: PetscViewerASCIIPushTab(viewer);
1077: MatGetSize(mat, &rows, &cols);
1078: MatGetBlockSizes(mat, &rbs, &cbs);
1079: if (rbs != 1 || cbs != 1) {
1080: if (rbs != cbs) PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs);
1081: else PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs);
1082: } else PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols);
1083: if (mat->factortype) {
1084: MatSolverType solver;
1085: MatFactorGetSolverType(mat, &solver);
1086: PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver);
1087: }
1088: if (mat->ops->getinfo) {
1089: MatInfo info;
1090: MatGetInfo(mat, MAT_GLOBAL_SUM, &info);
1091: PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated);
1092: if (!mat->factortype) PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs);
1093: }
1094: MatGetNullSpace(mat, &nullsp);
1095: MatGetTransposeNullSpace(mat, &transnullsp);
1096: if (nullsp) PetscViewerASCIIPrintf(viewer, " has attached null space\n");
1097: if (transnullsp && transnullsp != nullsp) PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n");
1098: MatGetNearNullSpace(mat, &nullsp);
1099: if (nullsp) PetscViewerASCIIPrintf(viewer, " has attached near null space\n");
1100: PetscViewerASCIIPushTab(viewer);
1101: MatProductView(mat, viewer);
1102: PetscViewerASCIIPopTab(viewer);
1103: }
1104: } else if (issaws) {
1105: #if defined(PETSC_HAVE_SAWS)
1106: PetscMPIInt rank;
1108: PetscObjectName((PetscObject)mat);
1109: MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1110: if (!((PetscObject)mat)->amsmem && rank == 0) PetscObjectViewSAWs((PetscObject)mat, viewer);
1111: #endif
1112: } else if (isstring) {
1113: const char *type;
1114: MatGetType(mat, &type);
1115: PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type);
1116: PetscTryTypeMethod(mat, view, viewer);
1117: }
1118: if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1119: PetscViewerASCIIPushTab(viewer);
1120: PetscUseTypeMethod(mat, viewnative, viewer);
1121: PetscViewerASCIIPopTab(viewer);
1122: } else if (mat->ops->view) {
1123: PetscViewerASCIIPushTab(viewer);
1124: PetscUseTypeMethod(mat, view, viewer);
1125: PetscViewerASCIIPopTab(viewer);
1126: }
1127: if (isascii) {
1128: PetscViewerGetFormat(viewer, &format);
1129: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscViewerASCIIPopTab(viewer);
1130: }
1131: PetscLogEventEnd(MAT_View, mat, viewer, 0, 0);
1132: return 0;
1133: }
1135: #if defined(PETSC_USE_DEBUG)
1136: #include <../src/sys/totalview/tv_data_display.h>
1137: PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1138: {
1139: TV_add_row("Local rows", "int", &mat->rmap->n);
1140: TV_add_row("Local columns", "int", &mat->cmap->n);
1141: TV_add_row("Global rows", "int", &mat->rmap->N);
1142: TV_add_row("Global columns", "int", &mat->cmap->N);
1143: TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1144: return TV_format_OK;
1145: }
1146: #endif
1148: /*@C
1149: MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1150: with `MatView()`. The matrix format is determined from the options database.
1151: Generates a parallel MPI matrix if the communicator has more than one
1152: processor. The default matrix type is `MATAIJ`.
1154: Collective
1156: Input Parameters:
1157: + mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1158: or some related function before a call to `MatLoad()`
1159: - viewer - binary/HDF5 file viewer
1161: Options Database Keys:
1162: Used with block matrix formats (`MATSEQBAIJ`, ...) to specify
1163: block size
1164: . -matload_block_size <bs> - set block size
1166: Level: beginner
1168: Notes:
1169: If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1170: `Mat` before calling this routine if you wish to set it from the options database.
1172: `MatLoad()` automatically loads into the options database any options
1173: given in the file filename.info where filename is the name of the file
1174: that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1175: file will be ignored if you use the -viewer_binary_skip_info option.
1177: If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1178: sets the default matrix type AIJ and sets the local and global sizes.
1179: If type and/or size is already set, then the same are used.
1181: In parallel, each processor can load a subset of rows (or the
1182: entire matrix). This routine is especially useful when a large
1183: matrix is stored on disk and only part of it is desired on each
1184: processor. For example, a parallel solver may access only some of
1185: the rows from each processor. The algorithm used here reads
1186: relatively small blocks of data rather than reading the entire
1187: matrix and then subsetting it.
1189: Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1190: Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1191: or the sequence like
1192: .vb
1193: `PetscViewer` v;
1194: `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1195: `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1196: `PetscViewerSetFromOptions`(v);
1197: `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1198: `PetscViewerFileSetName`(v,"datafile");
1199: .ve
1200: The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1201: $ -viewer_type {binary,hdf5}
1203: See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1204: and src/mat/tutorials/ex10.c with the second approach.
1206: Notes about the PETSc binary format:
1207: In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1208: is read onto rank 0 and then shipped to its destination rank, one after another.
1209: Multiple objects, both matrices and vectors, can be stored within the same file.
1210: Their PetscObject name is ignored; they are loaded in the order of their storage.
1212: Most users should not need to know the details of the binary storage
1213: format, since `MatLoad()` and `MatView()` completely hide these details.
1214: But for anyone who's interested, the standard binary matrix storage
1215: format is
1217: $ PetscInt MAT_FILE_CLASSID
1218: $ PetscInt number of rows
1219: $ PetscInt number of columns
1220: $ PetscInt total number of nonzeros
1221: $ PetscInt *number nonzeros in each row
1222: $ PetscInt *column indices of all nonzeros (starting index is zero)
1223: $ PetscScalar *values of all nonzeros
1225: PETSc automatically does the byte swapping for
1226: machines that store the bytes reversed, e.g. DEC alpha, freebsd,
1227: Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1228: read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1229: and `PetscBinaryWrite()` to see how this may be done.
1231: Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1232: In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1233: Each processor's chunk is loaded independently by its owning rank.
1234: Multiple objects, both matrices and vectors, can be stored within the same file.
1235: They are looked up by their PetscObject name.
1237: As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1238: by default the same structure and naming of the AIJ arrays and column count
1239: within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1240: $ save example.mat A b -v7.3
1241: can be directly read by this routine (see Reference 1 for details).
1242: Note that depending on your MATLAB version, this format might be a default,
1243: otherwise you can set it as default in Preferences.
1245: Unless -nocompression flag is used to save the file in MATLAB,
1246: PETSc must be configured with ZLIB package.
1248: See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1250: Current HDF5 (MAT-File) limitations:
1251: This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1253: Corresponding `MatView()` is not yet implemented.
1255: The loaded matrix is actually a transpose of the original one in MATLAB,
1256: unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1257: With this format, matrix is automatically transposed by PETSc,
1258: unless the matrix is marked as SPD or symmetric
1259: (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1261: References:
1262: . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1264: .seealso: `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1265: @*/
1266: PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1267: {
1268: PetscBool flg;
1273: if (!((PetscObject)mat)->type_name) MatSetType(mat, MATAIJ);
1275: flg = PETSC_FALSE;
1276: PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL);
1277: if (flg) {
1278: MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE);
1279: MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE);
1280: }
1281: flg = PETSC_FALSE;
1282: PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL);
1283: if (flg) MatSetOption(mat, MAT_SPD, PETSC_TRUE);
1285: PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0);
1286: PetscUseTypeMethod(mat, load, viewer);
1287: PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0);
1288: return 0;
1289: }
1291: static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1292: {
1293: Mat_Redundant *redund = *redundant;
1295: if (redund) {
1296: if (redund->matseq) { /* via MatCreateSubMatrices() */
1297: ISDestroy(&redund->isrow);
1298: ISDestroy(&redund->iscol);
1299: MatDestroySubMatrices(1, &redund->matseq);
1300: } else {
1301: PetscFree2(redund->send_rank, redund->recv_rank);
1302: PetscFree(redund->sbuf_j);
1303: PetscFree(redund->sbuf_a);
1304: for (PetscInt i = 0; i < redund->nrecvs; i++) {
1305: PetscFree(redund->rbuf_j[i]);
1306: PetscFree(redund->rbuf_a[i]);
1307: }
1308: PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a);
1309: }
1311: if (redund->subcomm) PetscCommDestroy(&redund->subcomm);
1312: PetscFree(redund);
1313: }
1314: return 0;
1315: }
1317: /*@C
1318: MatDestroy - Frees space taken by a matrix.
1320: Collective
1322: Input Parameter:
1323: . A - the matrix
1325: Level: beginner
1327: Developer Note:
1328: Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1329: `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1330: `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1331: if changes are needed here.
1333: .seealso: `Mat`, `MatCreate()`
1334: @*/
1335: PetscErrorCode MatDestroy(Mat *A)
1336: {
1337: if (!*A) return 0;
1339: if (--((PetscObject)(*A))->refct > 0) {
1340: *A = NULL;
1341: return 0;
1342: }
1344: /* if memory was published with SAWs then destroy it */
1345: PetscObjectSAWsViewOff((PetscObject)*A);
1346: PetscTryTypeMethod((*A), destroy);
1348: PetscFree((*A)->factorprefix);
1349: PetscFree((*A)->defaultvectype);
1350: PetscFree((*A)->defaultrandtype);
1351: PetscFree((*A)->bsizes);
1352: PetscFree((*A)->solvertype);
1353: for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscFree((*A)->preferredordering[i]);
1354: if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1355: MatDestroy_Redundant(&(*A)->redundant);
1356: MatProductClear(*A);
1357: MatNullSpaceDestroy(&(*A)->nullsp);
1358: MatNullSpaceDestroy(&(*A)->transnullsp);
1359: MatNullSpaceDestroy(&(*A)->nearnullsp);
1360: MatDestroy(&(*A)->schur);
1361: PetscLayoutDestroy(&(*A)->rmap);
1362: PetscLayoutDestroy(&(*A)->cmap);
1363: PetscHeaderDestroy(A);
1364: return 0;
1365: }
1367: /*@C
1368: MatSetValues - Inserts or adds a block of values into a matrix.
1369: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1370: MUST be called after all calls to `MatSetValues()` have been completed.
1372: Not Collective
1374: Input Parameters:
1375: + mat - the matrix
1376: . v - a logically two-dimensional array of values
1377: . m, idxm - the number of rows and their global indices
1378: . n, idxn - the number of columns and their global indices
1379: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1381: Level: beginner
1383: Notes:
1384: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1385: `MatSetUp()` before using this routine
1387: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1389: Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1390: options cannot be mixed without intervening calls to the assembly
1391: routines.
1393: `MatSetValues()` uses 0-based row and column numbers in Fortran
1394: as well as in C.
1396: Negative indices may be passed in idxm and idxn, these rows and columns are
1397: simply ignored. This allows easily inserting element stiffness matrices
1398: with homogeneous Dirchlet boundary conditions that you don't want represented
1399: in the matrix.
1401: Efficiency Alert:
1402: The routine `MatSetValuesBlocked()` may offer much better efficiency
1403: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1405: Developer Note:
1406: This is labeled with C so does not automatically generate Fortran stubs and interfaces
1407: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1409: .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1410: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1411: @*/
1412: PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1413: {
1417: if (!m || !n) return 0; /* no values to insert */
1420: MatCheckPreallocated(mat, 1);
1422: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1425: if (PetscDefined(USE_DEBUG)) {
1426: PetscInt i, j;
1429: for (i = 0; i < m; i++) {
1430: for (j = 0; j < n; j++) {
1431: if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1432: #if defined(PETSC_USE_COMPLEX)
1433: 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]);
1434: #else
1435: 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]);
1436: #endif
1437: }
1438: }
1441: }
1443: if (mat->assembled) {
1444: mat->was_assembled = PETSC_TRUE;
1445: mat->assembled = PETSC_FALSE;
1446: }
1447: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1448: PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1449: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1450: return 0;
1451: }
1453: /*@C
1454: MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1455: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1456: MUST be called after all calls to `MatSetValues()` have been completed.
1458: Not Collective
1460: Input Parameters:
1461: + mat - the matrix
1462: . v - a logically two-dimensional array of values
1463: . ism - the rows to provide
1464: . isn - the columns to provide
1465: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1467: Level: beginner
1469: Notes:
1470: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1471: `MatSetUp()` before using this routine
1473: By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1475: Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1476: options cannot be mixed without intervening calls to the assembly
1477: routines.
1479: `MatSetValues()` uses 0-based row and column numbers in Fortran
1480: as well as in C.
1482: Negative indices may be passed in ism and isn, these rows and columns are
1483: simply ignored. This allows easily inserting element stiffness matrices
1484: with homogeneous Dirchlet boundary conditions that you don't want represented
1485: in the matrix.
1487: Efficiency Alert:
1488: The routine `MatSetValuesBlocked()` may offer much better efficiency
1489: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1491: This is currently not optimized for any particular `ISType`
1493: Developer Notes:
1494: This is labeled with C so does not automatically generate Fortran stubs and interfaces
1495: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1497: .seealso: `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1498: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1499: @*/
1500: PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1501: {
1502: PetscInt m, n;
1503: const PetscInt *rows, *cols;
1507: ISGetIndices(ism, &rows);
1508: ISGetIndices(isn, &cols);
1509: ISGetLocalSize(ism, &m);
1510: ISGetLocalSize(isn, &n);
1511: MatSetValues(mat, m, rows, n, cols, v, addv);
1512: ISRestoreIndices(ism, &rows);
1513: ISRestoreIndices(isn, &cols);
1514: return 0;
1515: }
1517: /*@
1518: MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1519: values into a matrix
1521: Not Collective
1523: Input Parameters:
1524: + mat - the matrix
1525: . row - the (block) row to set
1526: - v - a logically two-dimensional array of values
1528: Level: intermediate
1530: Notes:
1531: The values, `v`, are column-oriented (for the block version) and sorted
1533: All the nonzeros in the row must be provided
1535: The matrix must have previously had its column indices set
1537: The row must belong to this process
1539: .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1540: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1541: @*/
1542: PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1543: {
1544: PetscInt globalrow;
1549: ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow);
1550: MatSetValuesRow(mat, globalrow, v);
1551: return 0;
1552: }
1554: /*@
1555: MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1556: values into a matrix
1558: Not Collective
1560: Input Parameters:
1561: + mat - the matrix
1562: . row - the (block) row to set
1563: - 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
1565: Level: advanced
1567: Notes:
1568: The values, `v`, are column-oriented for the block version.
1570: All the nonzeros in the row must be provided
1572: THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1574: The row must belong to this process
1576: .seealso: `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1577: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1578: @*/
1579: PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1580: {
1584: MatCheckPreallocated(mat, 1);
1588: mat->insertmode = INSERT_VALUES;
1590: if (mat->assembled) {
1591: mat->was_assembled = PETSC_TRUE;
1592: mat->assembled = PETSC_FALSE;
1593: }
1594: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1595: PetscUseTypeMethod(mat, setvaluesrow, row, v);
1596: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1597: return 0;
1598: }
1600: /*@
1601: MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1602: Using structured grid indexing
1604: Not Collective
1606: Input Parameters:
1607: + mat - the matrix
1608: . m - number of rows being entered
1609: . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1610: . n - number of columns being entered
1611: . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1612: . v - a logically two-dimensional array of values
1613: - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1615: Level: beginner
1617: Notes:
1618: By default the values, `v`, are row-oriented. See `MatSetOption()` for other options.
1620: Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1621: options cannot be mixed without intervening calls to the assembly
1622: routines.
1624: The grid coordinates are across the entire grid, not just the local portion
1626: `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1627: as well as in C.
1629: For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1631: In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1632: or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1634: The columns and rows in the stencil passed in MUST be contained within the
1635: ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1636: if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1637: local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1638: first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1640: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1641: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1642: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1643: `DM_BOUNDARY_PERIODIC` boundary type.
1645: 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
1646: a single value per point) you can skip filling those indices.
1648: Inspired by the structured grid interface to the HYPRE package
1649: (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1651: Efficiency Alert:
1652: The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1653: for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1655: Fortran Note:
1656: In Fortran idxm and idxn should be declared as
1657: $ MatStencil idxm(4,m),idxn(4,n)
1658: and the values inserted using
1659: .vb
1660: idxm(MatStencil_i,1) = i
1661: idxm(MatStencil_j,1) = j
1662: idxm(MatStencil_k,1) = k
1663: idxm(MatStencil_c,1) = c
1664: etc
1665: .ve
1667: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1668: `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1669: @*/
1670: PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1671: {
1672: PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1673: PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1674: PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1676: if (!m || !n) return 0; /* no values to insert */
1682: if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1683: jdxm = buf;
1684: jdxn = buf + m;
1685: } else {
1686: PetscMalloc2(m, &bufm, n, &bufn);
1687: jdxm = bufm;
1688: jdxn = bufn;
1689: }
1690: for (i = 0; i < m; i++) {
1691: for (j = 0; j < 3 - sdim; j++) dxm++;
1692: tmp = *dxm++ - starts[0];
1693: for (j = 0; j < dim - 1; j++) {
1694: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1695: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1696: }
1697: if (mat->stencil.noc) dxm++;
1698: jdxm[i] = tmp;
1699: }
1700: for (i = 0; i < n; i++) {
1701: for (j = 0; j < 3 - sdim; j++) dxn++;
1702: tmp = *dxn++ - starts[0];
1703: for (j = 0; j < dim - 1; j++) {
1704: if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1705: else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1706: }
1707: if (mat->stencil.noc) dxn++;
1708: jdxn[i] = tmp;
1709: }
1710: MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv);
1711: PetscFree2(bufm, bufn);
1712: return 0;
1713: }
1715: /*@
1716: MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1717: Using structured grid indexing
1719: Not Collective
1721: Input Parameters:
1722: + mat - the matrix
1723: . m - number of rows being entered
1724: . idxm - grid coordinates for matrix rows being entered
1725: . n - number of columns being entered
1726: . idxn - grid coordinates for matrix columns being entered
1727: . v - a logically two-dimensional array of values
1728: - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1730: Level: beginner
1732: Notes:
1733: By default the values, `v`, are row-oriented and unsorted.
1734: See `MatSetOption()` for other options.
1736: Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1737: options cannot be mixed without intervening calls to the assembly
1738: routines.
1740: The grid coordinates are across the entire grid, not just the local portion
1742: `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1743: as well as in C.
1745: For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1747: In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1748: or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1750: The columns and rows in the stencil passed in MUST be contained within the
1751: ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1752: if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1753: local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1754: first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1756: Negative indices may be passed in idxm and idxn, these rows and columns are
1757: simply ignored. This allows easily inserting element stiffness matrices
1758: with homogeneous Dirchlet boundary conditions that you don't want represented
1759: in the matrix.
1761: Inspired by the structured grid interface to the HYPRE package
1762: (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1764: Fortran Note:
1765: In Fortran idxm and idxn should be declared as
1766: $ MatStencil idxm(4,m),idxn(4,n)
1767: and the values inserted using
1768: .vb
1769: idxm(MatStencil_i,1) = i
1770: idxm(MatStencil_j,1) = j
1771: idxm(MatStencil_k,1) = k
1772: etc
1773: .ve
1775: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1776: `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1777: `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1778: @*/
1779: PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1780: {
1781: PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1782: PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1783: PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1785: if (!m || !n) return 0; /* no values to insert */
1792: if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1793: jdxm = buf;
1794: jdxn = buf + m;
1795: } else {
1796: PetscMalloc2(m, &bufm, n, &bufn);
1797: jdxm = bufm;
1798: jdxn = bufn;
1799: }
1800: for (i = 0; i < m; i++) {
1801: for (j = 0; j < 3 - sdim; j++) dxm++;
1802: tmp = *dxm++ - starts[0];
1803: for (j = 0; j < sdim - 1; j++) {
1804: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1805: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1806: }
1807: dxm++;
1808: jdxm[i] = tmp;
1809: }
1810: for (i = 0; i < n; i++) {
1811: for (j = 0; j < 3 - sdim; j++) dxn++;
1812: tmp = *dxn++ - starts[0];
1813: for (j = 0; j < sdim - 1; j++) {
1814: if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1815: else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1816: }
1817: dxn++;
1818: jdxn[i] = tmp;
1819: }
1820: MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv);
1821: PetscFree2(bufm, bufn);
1822: return 0;
1823: }
1825: /*@
1826: MatSetStencil - Sets the grid information for setting values into a matrix via
1827: `MatSetValuesStencil()`
1829: Not Collective
1831: Input Parameters:
1832: + mat - the matrix
1833: . dim - dimension of the grid 1, 2, or 3
1834: . dims - number of grid points in x, y, and z direction, including ghost points on your processor
1835: . starts - starting point of ghost nodes on your processor in x, y, and z direction
1836: - dof - number of degrees of freedom per node
1838: Level: beginner
1840: Notes:
1841: Inspired by the structured grid interface to the HYPRE package
1842: (www.llnl.gov/CASC/hyper)
1844: For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1845: user.
1847: .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1848: `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1849: @*/
1850: PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1851: {
1856: mat->stencil.dim = dim + (dof > 1);
1857: for (PetscInt i = 0; i < dim; i++) {
1858: mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */
1859: mat->stencil.starts[i] = starts[dim - i - 1];
1860: }
1861: mat->stencil.dims[dim] = dof;
1862: mat->stencil.starts[dim] = 0;
1863: mat->stencil.noc = (PetscBool)(dof == 1);
1864: return 0;
1865: }
1867: /*@C
1868: MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1870: Not Collective
1872: Input Parameters:
1873: + mat - the matrix
1874: . v - a logically two-dimensional array of values
1875: . m - the number of block rows
1876: . idxm - the global block indices
1877: . n - the number of block columns
1878: . idxn - the global block indices
1879: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1881: Level: intermediate
1883: Notes:
1884: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1885: MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1887: The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1888: NOT the total number of rows/columns; for example, if the block size is 2 and
1889: you are passing in values for rows 2,3,4,5 then m would be 2 (not 4).
1890: The values in idxm would be 1 2; that is the first index for each block divided by
1891: the block size.
1893: Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1894: preallocating it).
1896: By default the values, `v`, are row-oriented, so the layout of
1897: `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1899: Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1900: options cannot be mixed without intervening calls to the assembly
1901: routines.
1903: `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1904: as well as in C.
1906: Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1907: simply ignored. This allows easily inserting element stiffness matrices
1908: with homogeneous Dirchlet boundary conditions that you don't want represented
1909: in the matrix.
1911: Each time an entry is set within a sparse matrix via `MatSetValues()`,
1912: internal searching must be done to determine where to place the
1913: data in the matrix storage space. By instead inserting blocks of
1914: entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1915: reduced.
1917: Example:
1918: .vb
1919: Suppose m=n=2 and block size(bs) = 2 The array is
1921: 1 2 | 3 4
1922: 5 6 | 7 8
1923: - - - | - - -
1924: 9 10 | 11 12
1925: 13 14 | 15 16
1927: v[] should be passed in like
1928: v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1930: If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1931: v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1932: .ve
1934: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1935: @*/
1936: PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1937: {
1941: if (!m || !n) return 0; /* no values to insert */
1944: MatCheckPreallocated(mat, 1);
1945: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1947: if (PetscDefined(USE_DEBUG)) {
1950: }
1951: if (PetscDefined(USE_DEBUG)) {
1952: PetscInt rbs, cbs, M, N, i;
1953: MatGetBlockSizes(mat, &rbs, &cbs);
1954: MatGetSize(mat, &M, &N);
1957: }
1958: if (mat->assembled) {
1959: mat->was_assembled = PETSC_TRUE;
1960: mat->assembled = PETSC_FALSE;
1961: }
1962: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1963: if (mat->ops->setvaluesblocked) {
1964: PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1965: } else {
1966: PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1967: PetscInt i, j, bs, cbs;
1969: MatGetBlockSizes(mat, &bs, &cbs);
1970: if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1971: iidxm = buf;
1972: iidxn = buf + m * bs;
1973: } else {
1974: PetscMalloc2(m * bs, &bufr, n * cbs, &bufc);
1975: iidxm = bufr;
1976: iidxn = bufc;
1977: }
1978: for (i = 0; i < m; i++) {
1979: for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
1980: }
1981: if (m != n || bs != cbs || idxm != idxn) {
1982: for (i = 0; i < n; i++) {
1983: for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
1984: }
1985: } else iidxn = iidxm;
1986: MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv);
1987: PetscFree2(bufr, bufc);
1988: }
1989: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1990: return 0;
1991: }
1993: /*@C
1994: MatGetValues - Gets a block of local values from a matrix.
1996: Not Collective; can only return values that are owned by the give process
1998: Input Parameters:
1999: + mat - the matrix
2000: . v - a logically two-dimensional array for storing the values
2001: . m - the number of rows
2002: . idxm - the global indices of the rows
2003: . n - the number of columns
2004: - idxn - the global indices of the columns
2006: Level: advanced
2008: Notes:
2009: The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2010: The values, `v`, are then returned in a row-oriented format,
2011: analogous to that used by default in `MatSetValues()`.
2013: `MatGetValues()` uses 0-based row and column numbers in
2014: Fortran as well as in C.
2016: `MatGetValues()` requires that the matrix has been assembled
2017: with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to
2018: `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2019: without intermediate matrix assembly.
2021: Negative row or column indices will be ignored and those locations in `v` will be
2022: left unchanged.
2024: For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2025: That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2026: from `MatGetOwnershipRange`(mat,&rstart,&rend).
2028: .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2029: @*/
2030: PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2031: {
2034: if (!m || !n) return 0;
2040: MatCheckPreallocated(mat, 1);
2042: PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2043: PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2044: PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2045: return 0;
2046: }
2048: /*@C
2049: MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2050: defined previously by `MatSetLocalToGlobalMapping()`
2052: Not Collective
2054: Input Parameters:
2055: + mat - the matrix
2056: . nrow - number of rows
2057: . irow - the row local indices
2058: . ncol - number of columns
2059: - icol - the column local indices
2061: Output Parameter:
2062: . y - a logically two-dimensional array of values
2064: Level: advanced
2066: Notes:
2067: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2069: 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,
2070: are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2071: determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2072: with `MatSetLocalToGlobalMapping()`.
2074: Developer Note:
2075: This is labelled with C so does not automatically generate Fortran stubs and interfaces
2076: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2078: .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2079: `MatSetValuesLocal()`, `MatGetValues()`
2080: @*/
2081: PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2082: {
2086: MatCheckPreallocated(mat, 1);
2087: if (!nrow || !ncol) return 0; /* no values to retrieve */
2090: if (PetscDefined(USE_DEBUG)) {
2093: }
2095: PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2096: if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2097: else {
2098: PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2099: if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2100: irowm = buf;
2101: icolm = buf + nrow;
2102: } else {
2103: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2104: irowm = bufr;
2105: icolm = bufc;
2106: }
2109: ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm);
2110: ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm);
2111: MatGetValues(mat, nrow, irowm, ncol, icolm, y);
2112: PetscFree2(bufr, bufc);
2113: }
2114: PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2115: return 0;
2116: }
2118: /*@
2119: MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2120: the same size. Currently, this can only be called once and creates the given matrix.
2122: Not Collective
2124: Input Parameters:
2125: + mat - the matrix
2126: . nb - the number of blocks
2127: . bs - the number of rows (and columns) in each block
2128: . rows - a concatenation of the rows for each block
2129: - v - a concatenation of logically two-dimensional arrays of values
2131: Level: advanced
2133: Note:
2134: `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2136: In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2138: .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2139: `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2140: @*/
2141: PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2142: {
2147: PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2149: PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0);
2150: if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2151: else {
2152: for (PetscInt b = 0; b < nb; ++b) MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES);
2153: }
2154: PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0);
2155: return 0;
2156: }
2158: /*@
2159: MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2160: the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2161: using a local (per-processor) numbering.
2163: Not Collective
2165: Input Parameters:
2166: + x - the matrix
2167: . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2168: - cmapping - column mapping
2170: Level: intermediate
2172: Note:
2173: If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2175: .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2176: @*/
2177: PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2178: {
2183: if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2184: else {
2185: PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping);
2186: PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping);
2187: }
2188: return 0;
2189: }
2191: /*@
2192: MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2194: Not Collective
2196: Input Parameter:
2197: . A - the matrix
2199: Output Parameters:
2200: + rmapping - row mapping
2201: - cmapping - column mapping
2203: Level: advanced
2205: .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2206: @*/
2207: PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2208: {
2211: if (rmapping) {
2213: *rmapping = A->rmap->mapping;
2214: }
2215: if (cmapping) {
2217: *cmapping = A->cmap->mapping;
2218: }
2219: return 0;
2220: }
2222: /*@
2223: MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2225: Logically Collective
2227: Input Parameters:
2228: + A - the matrix
2229: . rmap - row layout
2230: - cmap - column layout
2232: Level: advanced
2234: Note:
2235: The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2237: .seealso: `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2238: @*/
2239: PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2240: {
2242: PetscLayoutReference(rmap, &A->rmap);
2243: PetscLayoutReference(cmap, &A->cmap);
2244: return 0;
2245: }
2247: /*@
2248: MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2250: Not Collective
2252: Input Parameter:
2253: . A - the matrix
2255: Output Parameters:
2256: + rmap - row layout
2257: - cmap - column layout
2259: Level: advanced
2261: .seealso: `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2262: @*/
2263: PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2264: {
2267: if (rmap) {
2269: *rmap = A->rmap;
2270: }
2271: if (cmap) {
2273: *cmap = A->cmap;
2274: }
2275: return 0;
2276: }
2278: /*@C
2279: MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2280: using a local numbering of the nodes.
2282: Not Collective
2284: Input Parameters:
2285: + mat - the matrix
2286: . nrow - number of rows
2287: . irow - the row local indices
2288: . ncol - number of columns
2289: . icol - the column local indices
2290: . y - a logically two-dimensional array of values
2291: - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2293: Level: intermediate
2295: Notes:
2296: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2297: `MatSetUp()` before using this routine
2299: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2301: Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2302: options cannot be mixed without intervening calls to the assembly
2303: routines.
2305: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2306: MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2308: Developer Note:
2309: This is labeled with C so does not automatically generate Fortran stubs and interfaces
2310: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2312: .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2313: `MatGetValuesLocal()`
2314: @*/
2315: PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2316: {
2320: MatCheckPreallocated(mat, 1);
2321: if (!nrow || !ncol) return 0; /* no values to insert */
2324: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2326: if (PetscDefined(USE_DEBUG)) {
2329: }
2331: if (mat->assembled) {
2332: mat->was_assembled = PETSC_TRUE;
2333: mat->assembled = PETSC_FALSE;
2334: }
2335: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2336: if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2337: else {
2338: PetscInt buf[8192], *bufr = NULL, *bufc = NULL;
2339: const PetscInt *irowm, *icolm;
2341: if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2342: bufr = buf;
2343: bufc = buf + nrow;
2344: irowm = bufr;
2345: icolm = bufc;
2346: } else {
2347: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2348: irowm = bufr;
2349: icolm = bufc;
2350: }
2351: if (mat->rmap->mapping) ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr);
2352: else irowm = irow;
2353: if (mat->cmap->mapping) {
2354: if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2355: ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc);
2356: } else icolm = irowm;
2357: } else icolm = icol;
2358: MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv);
2359: if (bufr != buf) PetscFree2(bufr, bufc);
2360: }
2361: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2362: return 0;
2363: }
2365: /*@C
2366: MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2367: using a local ordering of the nodes a block at a time.
2369: Not Collective
2371: Input Parameters:
2372: + x - the matrix
2373: . nrow - number of rows
2374: . irow - the row local indices
2375: . ncol - number of columns
2376: . icol - the column local indices
2377: . y - a logically two-dimensional array of values
2378: - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2380: Level: intermediate
2382: Notes:
2383: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2384: `MatSetUp()` before using this routine
2386: If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2387: before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2389: Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2390: options cannot be mixed without intervening calls to the assembly
2391: routines.
2393: These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2394: MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2396: Developer Note:
2397: This is labeled with C so does not automatically generate Fortran stubs and interfaces
2398: because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2400: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2401: `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2402: @*/
2403: PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2404: {
2408: MatCheckPreallocated(mat, 1);
2409: if (!nrow || !ncol) return 0; /* no values to insert */
2412: if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2414: if (PetscDefined(USE_DEBUG)) {
2417: }
2419: if (mat->assembled) {
2420: mat->was_assembled = PETSC_TRUE;
2421: mat->assembled = PETSC_FALSE;
2422: }
2423: if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2424: PetscInt irbs, rbs;
2425: MatGetBlockSizes(mat, &rbs, NULL);
2426: ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs);
2428: }
2429: if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2430: PetscInt icbs, cbs;
2431: MatGetBlockSizes(mat, NULL, &cbs);
2432: ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs);
2434: }
2435: PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2436: if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2437: else {
2438: PetscInt buf[8192], *bufr = NULL, *bufc = NULL;
2439: const PetscInt *irowm, *icolm;
2441: if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2442: bufr = buf;
2443: bufc = buf + nrow;
2444: irowm = bufr;
2445: icolm = bufc;
2446: } else {
2447: PetscMalloc2(nrow, &bufr, ncol, &bufc);
2448: irowm = bufr;
2449: icolm = bufc;
2450: }
2451: if (mat->rmap->mapping) ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr);
2452: else irowm = irow;
2453: if (mat->cmap->mapping) {
2454: if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2455: ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc);
2456: } else icolm = irowm;
2457: } else icolm = icol;
2458: MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv);
2459: if (bufr != buf) PetscFree2(bufr, bufc);
2460: }
2461: PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2462: return 0;
2463: }
2465: /*@
2466: MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2468: Collective
2470: Input Parameters:
2471: + mat - the matrix
2472: - x - the vector to be multiplied
2474: Output Parameters:
2475: . y - the result
2477: Level: developer
2479: Note:
2480: The vectors `x` and `y` cannot be the same. I.e., one cannot
2481: call `MatMultDiagonalBlock`(A,y,y).
2483: .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2484: @*/
2485: PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2486: {
2495: MatCheckPreallocated(mat, 1);
2497: PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2498: PetscObjectStateIncrease((PetscObject)y);
2499: return 0;
2500: }
2502: /*@
2503: MatMult - Computes the matrix-vector product, y = Ax.
2505: Neighbor-wise Collective
2507: Input Parameters:
2508: + mat - the matrix
2509: - x - the vector to be multiplied
2511: Output Parameters:
2512: . y - the result
2514: Level: beginner
2516: Note:
2517: The vectors `x` and `y` cannot be the same. I.e., one cannot
2518: call `MatMult`(A,y,y).
2520: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2521: @*/
2522: PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2523: {
2535: VecSetErrorIfLocked(y, 3);
2536: if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2537: MatCheckPreallocated(mat, 1);
2539: VecLockReadPush(x);
2540: PetscLogEventBegin(MAT_Mult, mat, x, y, 0);
2541: PetscUseTypeMethod(mat, mult, x, y);
2542: PetscLogEventEnd(MAT_Mult, mat, x, y, 0);
2543: if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2544: VecLockReadPop(x);
2545: return 0;
2546: }
2548: /*@
2549: MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2551: Neighbor-wise Collective
2553: Input Parameters:
2554: + mat - the matrix
2555: - x - the vector to be multiplied
2557: Output Parameters:
2558: . y - the result
2560: Level: beginner
2562: Notes:
2563: The vectors `x` and `y` cannot be the same. I.e., one cannot
2564: call `MatMultTranspose`(A,y,y).
2566: For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2567: use `MatMultHermitianTranspose()`
2569: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2570: @*/
2571: PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2572: {
2573: PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2587: if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2588: MatCheckPreallocated(mat, 1);
2590: if (!mat->ops->multtranspose) {
2591: if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2593: } else op = mat->ops->multtranspose;
2594: PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0);
2595: VecLockReadPush(x);
2596: (*op)(mat, x, y);
2597: VecLockReadPop(x);
2598: PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0);
2599: PetscObjectStateIncrease((PetscObject)y);
2600: if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2601: return 0;
2602: }
2604: /*@
2605: MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2607: Neighbor-wise Collective
2609: Input Parameters:
2610: + mat - the matrix
2611: - x - the vector to be multilplied
2613: Output Parameters:
2614: . y - the result
2616: Level: beginner
2618: Notes:
2619: The vectors `x` and `y` cannot be the same. I.e., one cannot
2620: call `MatMultHermitianTranspose`(A,y,y).
2622: Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2624: For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2626: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2627: @*/
2628: PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2629: {
2642: MatCheckPreallocated(mat, 1);
2644: PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0);
2645: #if defined(PETSC_USE_COMPLEX)
2646: if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2647: VecLockReadPush(x);
2648: if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2649: else PetscUseTypeMethod(mat, mult, x, y);
2650: VecLockReadPop(x);
2651: } else {
2652: Vec w;
2653: VecDuplicate(x, &w);
2654: VecCopy(x, w);
2655: VecConjugate(w);
2656: MatMultTranspose(mat, w, y);
2657: VecDestroy(&w);
2658: VecConjugate(y);
2659: }
2660: PetscObjectStateIncrease((PetscObject)y);
2661: #else
2662: MatMultTranspose(mat, x, y);
2663: #endif
2664: PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0);
2665: return 0;
2666: }
2668: /*@
2669: MatMultAdd - Computes v3 = v2 + A * v1.
2671: Neighbor-wise Collective
2673: Input Parameters:
2674: + mat - the matrix
2675: - v1, v2 - the vectors
2677: Output Parameters:
2678: . v3 - the result
2680: Level: beginner
2682: Note:
2683: The vectors `v1` and `v3` cannot be the same. I.e., one cannot
2684: call `MatMultAdd`(A,v1,v2,v1).
2686: .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2687: @*/
2688: PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2689: {
2704: MatCheckPreallocated(mat, 1);
2706: PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3);
2707: VecLockReadPush(v1);
2708: PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2709: VecLockReadPop(v1);
2710: PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3);
2711: PetscObjectStateIncrease((PetscObject)v3);
2712: return 0;
2713: }
2715: /*@
2716: MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2718: Neighbor-wise Collective
2720: Input Parameters:
2721: + mat - the matrix
2722: - v1, v2 - the vectors
2724: Output Parameters:
2725: . v3 - the result
2727: Level: beginner
2729: Note:
2730: The vectors `v1` and `v3` cannot be the same. I.e., one cannot
2731: call `MatMultTransposeAdd`(A,v1,v2,v1).
2733: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2734: @*/
2735: PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2736: {
2737: PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2752: MatCheckPreallocated(mat, 1);
2754: PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3);
2755: VecLockReadPush(v1);
2756: (*op)(mat, v1, v2, v3);
2757: VecLockReadPop(v1);
2758: PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3);
2759: PetscObjectStateIncrease((PetscObject)v3);
2760: return 0;
2761: }
2763: /*@
2764: MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2766: Neighbor-wise Collective
2768: Input Parameters:
2769: + mat - the matrix
2770: - v1, v2 - the vectors
2772: Output Parameters:
2773: . v3 - the result
2775: Level: beginner
2777: Note:
2778: The vectors `v1` and `v3` cannot be the same. I.e., one cannot
2779: call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2781: .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2782: @*/
2783: PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2784: {
2797: MatCheckPreallocated(mat, 1);
2799: PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2800: VecLockReadPush(v1);
2801: if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2802: else {
2803: Vec w, z;
2804: VecDuplicate(v1, &w);
2805: VecCopy(v1, w);
2806: VecConjugate(w);
2807: VecDuplicate(v3, &z);
2808: MatMultTranspose(mat, w, z);
2809: VecDestroy(&w);
2810: VecConjugate(z);
2811: if (v2 != v3) {
2812: VecWAXPY(v3, 1.0, v2, z);
2813: } else {
2814: VecAXPY(v3, 1.0, z);
2815: }
2816: VecDestroy(&z);
2817: }
2818: VecLockReadPop(v1);
2819: PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2820: PetscObjectStateIncrease((PetscObject)v3);
2821: return 0;
2822: }
2824: /*@C
2825: MatGetFactorType - gets the type of factorization it is
2827: Not Collective
2829: Input Parameters:
2830: . mat - the matrix
2832: Output Parameters:
2833: . 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`
2835: Level: intermediate
2837: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2838: `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2839: @*/
2840: PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2841: {
2845: *t = mat->factortype;
2846: return 0;
2847: }
2849: /*@C
2850: MatSetFactorType - sets the type of factorization it is
2852: Logically Collective
2854: Input Parameters:
2855: + mat - the matrix
2856: - 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`
2858: Level: intermediate
2860: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2861: `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2862: @*/
2863: PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2864: {
2867: mat->factortype = t;
2868: return 0;
2869: }
2871: /*@C
2872: MatGetInfo - Returns information about matrix storage (number of
2873: nonzeros, memory, etc.).
2875: Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2877: Input Parameters:
2878: + mat - the matrix
2879: - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors)
2881: Output Parameters:
2882: . info - matrix information context
2884: Notes:
2885: The `MatInfo` context contains a variety of matrix data, including
2886: number of nonzeros allocated and used, number of mallocs during
2887: matrix assembly, etc. Additional information for factored matrices
2888: is provided (such as the fill ratio, number of mallocs during
2889: factorization, etc.). Much of this info is printed to `PETSC_STDOUT`
2890: when using the runtime options
2891: $ -info -mat_view ::ascii_info
2893: Example for C/C++ Users:
2894: See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2895: data within the MatInfo context. For example,
2896: .vb
2897: MatInfo info;
2898: Mat A;
2899: double mal, nz_a, nz_u;
2901: MatGetInfo(A,MAT_LOCAL,&info);
2902: mal = info.mallocs;
2903: nz_a = info.nz_allocated;
2904: .ve
2906: Example for Fortran Users:
2907: Fortran users should declare info as a double precision
2908: array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2909: of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2910: a complete list of parameter names.
2911: .vb
2912: double precision info(MAT_INFO_SIZE)
2913: double precision mal, nz_a
2914: Mat A
2915: integer ierr
2917: call MatGetInfo(A,MAT_LOCAL,info,ierr)
2918: mal = info(MAT_INFO_MALLOCS)
2919: nz_a = info(MAT_INFO_NZ_ALLOCATED)
2920: .ve
2922: Level: intermediate
2924: Developer Note:
2925: Fortran interface is not autogenerated as the
2926: interface definition cannot be generated correctly [due to MatInfo]
2928: .seealso: `Mat`, `MatInfo`, `MatStashGetInfo()`
2929: @*/
2930: PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2931: {
2935: MatCheckPreallocated(mat, 1);
2936: PetscUseTypeMethod(mat, getinfo, flag, info);
2937: return 0;
2938: }
2940: /*
2941: This is used by external packages where it is not easy to get the info from the actual
2942: matrix factorization.
2943: */
2944: PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2945: {
2946: PetscMemzero(info, sizeof(MatInfo));
2947: return 0;
2948: }
2950: /*@C
2951: MatLUFactor - Performs in-place LU factorization of matrix.
2953: Collective
2955: Input Parameters:
2956: + mat - the matrix
2957: . row - row permutation
2958: . col - column permutation
2959: - info - options for factorization, includes
2960: .vb
2961: fill - expected fill as ratio of original fill.
2962: dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2963: Run with the option -info to determine an optimal value to use
2964: .ve
2965: Level: developer
2967: Notes:
2968: Most users should employ the `KSP` interface for linear solvers
2969: instead of working directly with matrix algebra routines such as this.
2970: See, e.g., `KSPCreate()`.
2972: This changes the state of the matrix to a factored matrix; it cannot be used
2973: for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
2975: This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
2976: when not using `KSP`.
2978: Developer Note:
2979: The Fortran interface is not autogenerated as the
2980: interface definition cannot be generated correctly [due to `MatFactorInfo`]
2982: .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2983: `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2984: @*/
2985: PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
2986: {
2987: MatFactorInfo tinfo;
2996: MatCheckPreallocated(mat, 1);
2997: if (!info) {
2998: MatFactorInfoInitialize(&tinfo);
2999: info = &tinfo;
3000: }
3002: PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0);
3003: PetscUseTypeMethod(mat, lufactor, row, col, info);
3004: PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0);
3005: PetscObjectStateIncrease((PetscObject)mat);
3006: return 0;
3007: }
3009: /*@C
3010: MatILUFactor - Performs in-place ILU factorization of matrix.
3012: Collective
3014: Input Parameters:
3015: + mat - the matrix
3016: . row - row permutation
3017: . col - column permutation
3018: - info - structure containing
3019: .vb
3020: levels - number of levels of fill.
3021: expected fill - as ratio of original fill.
3022: 1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3023: missing diagonal entries)
3024: .ve
3026: Level: developer
3028: Notes:
3029: Most users should employ the `KSP` interface for linear solvers
3030: instead of working directly with matrix algebra routines such as this.
3031: See, e.g., `KSPCreate()`.
3033: Probably really in-place only when level of fill is zero, otherwise allocates
3034: new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3035: when not using `KSP`.
3037: Developer Note:
3038: The Fortran interface is not autogenerated as the
3039: interface definition cannot be generated correctly [due to MatFactorInfo]
3041: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3042: @*/
3043: PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3044: {
3053: MatCheckPreallocated(mat, 1);
3055: PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0);
3056: PetscUseTypeMethod(mat, ilufactor, row, col, info);
3057: PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0);
3058: PetscObjectStateIncrease((PetscObject)mat);
3059: return 0;
3060: }
3062: /*@C
3063: MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3064: Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3066: Collective on fact
3068: Input Parameters:
3069: + fact - the factor matrix obtained with `MatGetFactor()`
3070: . mat - the matrix
3071: . row, col - row and column permutations
3072: - info - options for factorization, includes
3073: .vb
3074: fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3075: dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3076: .ve
3078: Level: developer
3080: Notes:
3081: See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3083: Most users should employ the simplified `KSP` interface for linear solvers
3084: instead of working directly with matrix algebra routines such as this.
3085: See, e.g., `KSPCreate()`.
3087: Developer Note:
3088: The Fortran interface is not autogenerated as the
3089: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3091: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3092: @*/
3093: PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3094: {
3095: MatFactorInfo tinfo;
3105: if (!(fact)->ops->lufactorsymbolic) {
3106: MatSolverType stype;
3107: MatFactorGetSolverType(fact, &stype);
3108: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3109: }
3110: MatCheckPreallocated(mat, 2);
3111: if (!info) {
3112: MatFactorInfoInitialize(&tinfo);
3113: info = &tinfo;
3114: }
3116: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0);
3117: (fact->ops->lufactorsymbolic)(fact, mat, row, col, info);
3118: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0);
3119: PetscObjectStateIncrease((PetscObject)fact);
3120: return 0;
3121: }
3123: /*@C
3124: MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3125: Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3127: Collective on fact
3129: Input Parameters:
3130: + fact - the factor matrix obtained with `MatGetFactor()`
3131: . mat - the matrix
3132: - info - options for factorization
3134: Level: developer
3136: Notes:
3137: See `MatLUFactor()` for in-place factorization. See
3138: `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3140: Most users should employ the `KSP` interface for linear solvers
3141: instead of working directly with matrix algebra routines such as this.
3142: See, e.g., `KSPCreate()`.
3144: Developer Note:
3145: The Fortran interface is not autogenerated as the
3146: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3148: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3149: @*/
3150: PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3151: {
3152: MatFactorInfo tinfo;
3160: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3163: MatCheckPreallocated(mat, 2);
3164: if (!info) {
3165: MatFactorInfoInitialize(&tinfo);
3166: info = &tinfo;
3167: }
3169: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0);
3170: else PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0);
3171: (fact->ops->lufactornumeric)(fact, mat, info);
3172: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0);
3173: else PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0);
3174: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3175: PetscObjectStateIncrease((PetscObject)fact);
3176: return 0;
3177: }
3179: /*@C
3180: MatCholeskyFactor - Performs in-place Cholesky factorization of a
3181: symmetric matrix.
3183: Collective
3185: Input Parameters:
3186: + mat - the matrix
3187: . perm - row and column permutations
3188: - f - expected fill as ratio of original fill
3190: Level: developer
3192: Notes:
3193: See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`,
3194: `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3196: Most users should employ the `KSP` interface for linear solvers
3197: instead of working directly with matrix algebra routines such as this.
3198: See, e.g., `KSPCreate()`.
3200: Developer Note:
3201: The Fortran interface is not autogenerated as the
3202: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3204: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3205: `MatGetOrdering()`
3206: @*/
3207: PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3208: {
3209: MatFactorInfo tinfo;
3218: MatCheckPreallocated(mat, 1);
3219: if (!info) {
3220: MatFactorInfoInitialize(&tinfo);
3221: info = &tinfo;
3222: }
3224: PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0);
3225: PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3226: PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0);
3227: PetscObjectStateIncrease((PetscObject)mat);
3228: return 0;
3229: }
3231: /*@C
3232: MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3233: of a symmetric matrix.
3235: Collective on fact
3237: Input Parameters:
3238: + fact - the factor matrix obtained with `MatGetFactor()`
3239: . mat - the matrix
3240: . perm - row and column permutations
3241: - info - options for factorization, includes
3242: .vb
3243: fill - expected fill as ratio of original fill.
3244: dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3245: Run with the option -info to determine an optimal value to use
3246: .ve
3248: Level: developer
3250: Notes:
3251: See `MatLUFactorSymbolic()` for the nonsymmetric case. See also
3252: `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3254: Most users should employ the `KSP` interface for linear solvers
3255: instead of working directly with matrix algebra routines such as this.
3256: See, e.g., `KSPCreate()`.
3258: Developer Note:
3259: The Fortran interface is not autogenerated as the
3260: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3262: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3263: `MatGetOrdering()`
3264: @*/
3265: PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3266: {
3267: MatFactorInfo tinfo;
3277: if (!(fact)->ops->choleskyfactorsymbolic) {
3278: MatSolverType stype;
3279: MatFactorGetSolverType(fact, &stype);
3280: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3281: }
3282: MatCheckPreallocated(mat, 2);
3283: if (!info) {
3284: MatFactorInfoInitialize(&tinfo);
3285: info = &tinfo;
3286: }
3288: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3289: (fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info);
3290: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3291: PetscObjectStateIncrease((PetscObject)fact);
3292: return 0;
3293: }
3295: /*@C
3296: MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3297: of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3298: `MatCholeskyFactorSymbolic()`.
3300: Collective on fact
3302: Input Parameters:
3303: + fact - the factor matrix obtained with `MatGetFactor()`
3304: . mat - the initial matrix
3305: . info - options for factorization
3306: - fact - the symbolic factor of mat
3308: Level: developer
3310: Note:
3311: Most users should employ the `KSP` interface for linear solvers
3312: instead of working directly with matrix algebra routines such as this.
3313: See, e.g., `KSPCreate()`.
3315: Developer Note:
3316: The Fortran interface is not autogenerated as the
3317: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3319: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3320: @*/
3321: PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3322: {
3323: MatFactorInfo tinfo;
3332: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3333: MatCheckPreallocated(mat, 2);
3334: if (!info) {
3335: MatFactorInfoInitialize(&tinfo);
3336: info = &tinfo;
3337: }
3339: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3340: else PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0);
3341: (fact->ops->choleskyfactornumeric)(fact, mat, info);
3342: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3343: else PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0);
3344: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3345: PetscObjectStateIncrease((PetscObject)fact);
3346: return 0;
3347: }
3349: /*@
3350: MatQRFactor - Performs in-place QR factorization of matrix.
3352: Collective
3354: Input Parameters:
3355: + mat - the matrix
3356: . col - column permutation
3357: - info - options for factorization, includes
3358: .vb
3359: fill - expected fill as ratio of original fill.
3360: dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3361: Run with the option -info to determine an optimal value to use
3362: .ve
3364: Level: developer
3366: Notes:
3367: Most users should employ the `KSP` interface for linear solvers
3368: instead of working directly with matrix algebra routines such as this.
3369: See, e.g., `KSPCreate()`.
3371: This changes the state of the matrix to a factored matrix; it cannot be used
3372: for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3374: Developer Note:
3375: The Fortran interface is not autogenerated as the
3376: interface definition cannot be generated correctly [due to MatFactorInfo]
3378: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3379: `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3380: @*/
3381: PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3382: {
3389: MatCheckPreallocated(mat, 1);
3390: PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0);
3391: PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3392: PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0);
3393: PetscObjectStateIncrease((PetscObject)mat);
3394: return 0;
3395: }
3397: /*@
3398: MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3399: Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3401: Collective on fact
3403: Input Parameters:
3404: + fact - the factor matrix obtained with `MatGetFactor()`
3405: . mat - the matrix
3406: . col - column permutation
3407: - info - options for factorization, includes
3408: .vb
3409: fill - expected fill as ratio of original fill.
3410: dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3411: Run with the option -info to determine an optimal value to use
3412: .ve
3414: Level: developer
3416: Note:
3417: Most users should employ the `KSP` interface for linear solvers
3418: instead of working directly with matrix algebra routines such as this.
3419: See, e.g., `KSPCreate()`.
3421: Developer Note:
3422: The Fortran interface is not autogenerated as the
3423: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3425: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3426: @*/
3427: PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3428: {
3429: MatFactorInfo tinfo;
3438: MatCheckPreallocated(mat, 2);
3439: if (!info) {
3440: MatFactorInfoInitialize(&tinfo);
3441: info = &tinfo;
3442: }
3444: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0);
3445: PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3446: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0);
3447: PetscObjectStateIncrease((PetscObject)fact);
3448: return 0;
3449: }
3451: /*@
3452: MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3453: Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3455: Collective on fact
3457: Input Parameters:
3458: + fact - the factor matrix obtained with `MatGetFactor()`
3459: . mat - the matrix
3460: - info - options for factorization
3462: Level: developer
3464: Notes:
3465: See `MatQRFactor()` for in-place factorization.
3467: Most users should employ the `KSP` interface for linear solvers
3468: instead of working directly with matrix algebra routines such as this.
3469: See, e.g., `KSPCreate()`.
3471: Developer Note:
3472: The Fortran interface is not autogenerated as the
3473: interface definition cannot be generated correctly [due to `MatFactorInfo`]
3475: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3476: @*/
3477: PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3478: {
3479: MatFactorInfo tinfo;
3487: mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3489: MatCheckPreallocated(mat, 2);
3490: if (!info) {
3491: MatFactorInfoInitialize(&tinfo);
3492: info = &tinfo;
3493: }
3495: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0);
3496: else PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0);
3497: PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3498: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0);
3499: else PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0);
3500: MatViewFromOptions(fact, NULL, "-mat_factor_view");
3501: PetscObjectStateIncrease((PetscObject)fact);
3502: return 0;
3503: }
3505: /*@
3506: MatSolve - Solves A x = b, given a factored matrix.
3508: Neighbor-wise Collective
3510: Input Parameters:
3511: + mat - the factored matrix
3512: - b - the right-hand-side vector
3514: Output Parameter:
3515: . x - the result vector
3517: Level: developer
3519: Notes:
3520: The vectors `b` and `x` cannot be the same. I.e., one cannot
3521: call `MatSolve`(A,x,x).
3523: Most users should employ the `KSP` interface for linear solvers
3524: instead of working directly with matrix algebra routines such as this.
3525: See, e.g., `KSPCreate()`.
3527: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3528: @*/
3529: PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3530: {
3541: if (!mat->rmap->N && !mat->cmap->N) return 0;
3542: MatCheckPreallocated(mat, 1);
3544: PetscLogEventBegin(MAT_Solve, mat, b, x, 0);
3545: if (mat->factorerrortype) {
3546: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3547: VecSetInf(x);
3548: } else PetscUseTypeMethod(mat, solve, b, x);
3549: PetscLogEventEnd(MAT_Solve, mat, b, x, 0);
3550: PetscObjectStateIncrease((PetscObject)x);
3551: return 0;
3552: }
3554: static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3555: {
3556: Vec b, x;
3557: PetscInt N, i;
3558: PetscErrorCode (*f)(Mat, Vec, Vec);
3559: PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3561: if (A->factorerrortype) {
3562: PetscInfo(A, "MatFactorError %d\n", A->factorerrortype);
3563: MatSetInf(X);
3564: return 0;
3565: }
3566: f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3568: MatBoundToCPU(A, &Abound);
3569: if (!Abound) {
3570: PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "");
3571: PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "");
3572: }
3573: #if defined(PETSC_HAVE_CUDA)
3574: if (Bneedconv) MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B);
3575: if (Xneedconv) MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X);
3576: #elif (PETSC_HAVE_HIP)
3577: if (Bneedconv) MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B);
3578: if (Xneedconv) MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X);
3579: #endif
3580: MatGetSize(B, NULL, &N);
3581: for (i = 0; i < N; i++) {
3582: MatDenseGetColumnVecRead(B, i, &b);
3583: MatDenseGetColumnVecWrite(X, i, &x);
3584: (*f)(A, b, x);
3585: MatDenseRestoreColumnVecWrite(X, i, &x);
3586: MatDenseRestoreColumnVecRead(B, i, &b);
3587: }
3588: if (Bneedconv) MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B);
3589: if (Xneedconv) MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X);
3590: return 0;
3591: }
3593: /*@
3594: MatMatSolve - Solves A X = B, given a factored matrix.
3596: Neighbor-wise Collective
3598: Input Parameters:
3599: + A - the factored matrix
3600: - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3602: Output Parameter:
3603: . X - the result matrix (dense matrix)
3605: Level: developer
3607: Note:
3608: If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3609: otherwise, `B` and `X` cannot be the same.
3611: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3612: @*/
3613: PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3614: {
3624: if (!A->rmap->N && !A->cmap->N) return 0;
3626: MatCheckPreallocated(A, 1);
3628: PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3629: if (!A->ops->matsolve) {
3630: PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name);
3631: MatMatSolve_Basic(A, B, X, PETSC_FALSE);
3632: } else PetscUseTypeMethod(A, matsolve, B, X);
3633: PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3634: PetscObjectStateIncrease((PetscObject)X);
3635: return 0;
3636: }
3638: /*@
3639: MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3641: Neighbor-wise Collective
3643: Input Parameters:
3644: + A - the factored matrix
3645: - B - the right-hand-side matrix (`MATDENSE` matrix)
3647: Output Parameter:
3648: . X - the result matrix (dense matrix)
3650: Level: developer
3652: Note:
3653: The matrices `B` and `X` cannot be the same. I.e., one cannot
3654: call `MatMatSolveTranspose`(A,X,X).
3656: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3657: @*/
3658: PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3659: {
3671: if (!A->rmap->N && !A->cmap->N) return 0;
3673: MatCheckPreallocated(A, 1);
3675: PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3676: if (!A->ops->matsolvetranspose) {
3677: PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name);
3678: MatMatSolve_Basic(A, B, X, PETSC_TRUE);
3679: } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3680: PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3681: PetscObjectStateIncrease((PetscObject)X);
3682: return 0;
3683: }
3685: /*@
3686: MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3688: Neighbor-wise Collective
3690: Input Parameters:
3691: + A - the factored matrix
3692: - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3694: Output Parameter:
3695: . X - the result matrix (dense matrix)
3697: Level: developer
3699: Note:
3700: 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
3701: format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3703: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3704: @*/
3705: PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3706: {
3718: if (!A->rmap->N && !A->cmap->N) return 0;
3720: MatCheckPreallocated(A, 1);
3722: PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0);
3723: PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3724: PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0);
3725: PetscObjectStateIncrease((PetscObject)X);
3726: return 0;
3727: }
3729: /*@
3730: MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3731: U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3733: Neighbor-wise Collective
3735: Input Parameters:
3736: + mat - the factored matrix
3737: - b - the right-hand-side vector
3739: Output Parameter:
3740: . x - the result vector
3742: Level: developer
3744: Notes:
3745: `MatSolve()` should be used for most applications, as it performs
3746: a forward solve followed by a backward solve.
3748: The vectors `b` and `x` cannot be the same, i.e., one cannot
3749: call `MatForwardSolve`(A,x,x).
3751: For matrix in `MATSEQBAIJ` format with block size larger than 1,
3752: the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3753: `MatForwardSolve()` solves U^T*D y = b, and
3754: `MatBackwardSolve()` solves U x = y.
3755: Thus they do not provide a symmetric preconditioner.
3757: .seealso: `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3758: @*/
3759: PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3760: {
3771: if (!mat->rmap->N && !mat->cmap->N) return 0;
3772: MatCheckPreallocated(mat, 1);
3774: PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0);
3775: PetscUseTypeMethod(mat, forwardsolve, b, x);
3776: PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0);
3777: PetscObjectStateIncrease((PetscObject)x);
3778: return 0;
3779: }
3781: /*@
3782: MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3783: D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3785: Neighbor-wise Collective
3787: Input Parameters:
3788: + mat - the factored matrix
3789: - b - the right-hand-side vector
3791: Output Parameter:
3792: . x - the result vector
3794: Level: developer
3796: Notes:
3797: `MatSolve()` should be used for most applications, as it performs
3798: a forward solve followed by a backward solve.
3800: The vectors `b` and `x` cannot be the same. I.e., one cannot
3801: call `MatBackwardSolve`(A,x,x).
3803: For matrix in `MATSEQBAIJ` format with block size larger than 1,
3804: the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3805: `MatForwardSolve()` solves U^T*D y = b, and
3806: `MatBackwardSolve()` solves U x = y.
3807: Thus they do not provide a symmetric preconditioner.
3809: .seealso: `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3810: @*/
3811: PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3812: {
3823: if (!mat->rmap->N && !mat->cmap->N) return 0;
3824: MatCheckPreallocated(mat, 1);
3826: PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0);
3827: PetscUseTypeMethod(mat, backwardsolve, b, x);
3828: PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0);
3829: PetscObjectStateIncrease((PetscObject)x);
3830: return 0;
3831: }
3833: /*@
3834: MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3836: Neighbor-wise Collective
3838: Input Parameters:
3839: + mat - the factored matrix
3840: . b - the right-hand-side vector
3841: - y - the vector to be added to
3843: Output Parameter:
3844: . x - the result vector
3846: Level: developer
3848: Note:
3849: The vectors `b` and `x` cannot be the same. I.e., one cannot
3850: call `MatSolveAdd`(A,x,y,x).
3852: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3853: @*/
3854: PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3855: {
3856: PetscScalar one = 1.0;
3857: Vec tmp;
3873: if (!mat->rmap->N && !mat->cmap->N) return 0;
3874: MatCheckPreallocated(mat, 1);
3876: PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y);
3877: if (mat->factorerrortype) {
3878: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3879: VecSetInf(x);
3880: } else if (mat->ops->solveadd) {
3881: PetscUseTypeMethod(mat, solveadd, b, y, x);
3882: } else {
3883: /* do the solve then the add manually */
3884: if (x != y) {
3885: MatSolve(mat, b, x);
3886: VecAXPY(x, one, y);
3887: } else {
3888: VecDuplicate(x, &tmp);
3889: VecCopy(x, tmp);
3890: MatSolve(mat, b, x);
3891: VecAXPY(x, one, tmp);
3892: VecDestroy(&tmp);
3893: }
3894: }
3895: PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y);
3896: PetscObjectStateIncrease((PetscObject)x);
3897: return 0;
3898: }
3900: /*@
3901: MatSolveTranspose - Solves A' x = b, given a factored matrix.
3903: Neighbor-wise Collective
3905: Input Parameters:
3906: + mat - the factored matrix
3907: - b - the right-hand-side vector
3909: Output Parameter:
3910: . x - the result vector
3912: Level: developer
3914: Notes:
3915: The vectors `b` and `x` cannot be the same. I.e., one cannot
3916: call `MatSolveTranspose`(A,x,x).
3918: Most users should employ the `KSP` interface for linear solvers
3919: instead of working directly with matrix algebra routines such as this.
3920: See, e.g., `KSPCreate()`.
3922: .seealso: `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3923: @*/
3924: PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3925: {
3926: PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3937: if (!mat->rmap->N && !mat->cmap->N) return 0;
3938: MatCheckPreallocated(mat, 1);
3939: PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0);
3940: if (mat->factorerrortype) {
3941: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3942: VecSetInf(x);
3943: } else {
3945: (*f)(mat, b, x);
3946: }
3947: PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0);
3948: PetscObjectStateIncrease((PetscObject)x);
3949: return 0;
3950: }
3952: /*@
3953: MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3954: factored matrix.
3956: Neighbor-wise Collective
3958: Input Parameters:
3959: + mat - the factored matrix
3960: . b - the right-hand-side vector
3961: - y - the vector to be added to
3963: Output Parameter:
3964: . x - the result vector
3966: Level: developer
3968: Note:
3969: The vectors `b` and `x` cannot be the same. I.e., one cannot
3970: call `MatSolveTransposeAdd`(A,x,y,x).
3972: .seealso: `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
3973: @*/
3974: PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
3975: {
3976: PetscScalar one = 1.0;
3977: Vec tmp;
3978: PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
3993: if (!mat->rmap->N && !mat->cmap->N) return 0;
3994: MatCheckPreallocated(mat, 1);
3996: PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y);
3997: if (mat->factorerrortype) {
3998: PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3999: VecSetInf(x);
4000: } else if (f) {
4001: (*f)(mat, b, y, x);
4002: } else {
4003: /* do the solve then the add manually */
4004: if (x != y) {
4005: MatSolveTranspose(mat, b, x);
4006: VecAXPY(x, one, y);
4007: } else {
4008: VecDuplicate(x, &tmp);
4009: VecCopy(x, tmp);
4010: MatSolveTranspose(mat, b, x);
4011: VecAXPY(x, one, tmp);
4012: VecDestroy(&tmp);
4013: }
4014: }
4015: PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y);
4016: PetscObjectStateIncrease((PetscObject)x);
4017: return 0;
4018: }
4020: /*@
4021: MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4023: Neighbor-wise Collective
4025: Input Parameters:
4026: + mat - the matrix
4027: . b - the right hand side
4028: . omega - the relaxation factor
4029: . flag - flag indicating the type of SOR (see below)
4030: . shift - diagonal shift
4031: . its - the number of iterations
4032: - lits - the number of local iterations
4034: Output Parameter:
4035: . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4037: SOR Flags:
4038: + `SOR_FORWARD_SWEEP` - forward SOR
4039: . `SOR_BACKWARD_SWEEP` - backward SOR
4040: . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4041: . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4042: . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4043: . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4044: . `SOR_EISENSTAT` - SOR with Eisenstat trick
4045: . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4046: upper/lower triangular part of matrix to
4047: vector (with omega)
4048: - `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4050: Level: developer
4052: Notes:
4053: `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4054: `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4055: on each processor.
4057: Application programmers will not generally use `MatSOR()` directly,
4058: but instead will employ the `KSP`/`PC` interface.
4060: For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4062: Most users should employ the `KSP` interface for linear solvers
4063: instead of working directly with matrix algebra routines such as this.
4064: See, e.g., `KSPCreate()`.
4066: Vectors `x` and `b` CANNOT be the same
4068: Notes for Advanced Users:
4069: The flags are implemented as bitwise inclusive or operations.
4070: For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4071: to specify a zero initial guess for SSOR.
4073: Developer Note:
4074: We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4076: .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4077: @*/
4078: PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4079: {
4095: MatCheckPreallocated(mat, 1);
4096: PetscLogEventBegin(MAT_SOR, mat, b, x, 0);
4097: PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4098: PetscLogEventEnd(MAT_SOR, mat, b, x, 0);
4099: PetscObjectStateIncrease((PetscObject)x);
4100: return 0;
4101: }
4103: /*
4104: Default matrix copy routine.
4105: */
4106: PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4107: {
4108: PetscInt i, rstart = 0, rend = 0, nz;
4109: const PetscInt *cwork;
4110: const PetscScalar *vwork;
4112: if (B->assembled) MatZeroEntries(B);
4113: if (str == SAME_NONZERO_PATTERN) {
4114: MatGetOwnershipRange(A, &rstart, &rend);
4115: for (i = rstart; i < rend; i++) {
4116: MatGetRow(A, i, &nz, &cwork, &vwork);
4117: MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES);
4118: MatRestoreRow(A, i, &nz, &cwork, &vwork);
4119: }
4120: } else {
4121: MatAYPX(B, 0.0, A, str);
4122: }
4123: MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);
4124: MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);
4125: return 0;
4126: }
4128: /*@
4129: MatCopy - Copies a matrix to another matrix.
4131: Collective
4133: Input Parameters:
4134: + A - the matrix
4135: - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4137: Output Parameter:
4138: . B - where the copy is put
4140: Level: intermediate
4142: Notes:
4143: If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4145: `MatCopy()` copies the matrix entries of a matrix to another existing
4146: matrix (after first zeroing the second matrix). A related routine is
4147: `MatConvert()`, which first creates a new matrix and then copies the data.
4149: .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4150: @*/
4151: PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4152: {
4153: PetscInt i;
4160: MatCheckPreallocated(B, 2);
4164: A->cmap->N, B->cmap->N);
4165: MatCheckPreallocated(A, 1);
4166: if (A == B) return 0;
4168: PetscLogEventBegin(MAT_Copy, A, B, 0, 0);
4169: if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4170: else MatCopy_Basic(A, B, str);
4172: B->stencil.dim = A->stencil.dim;
4173: B->stencil.noc = A->stencil.noc;
4174: for (i = 0; i <= A->stencil.dim; i++) {
4175: B->stencil.dims[i] = A->stencil.dims[i];
4176: B->stencil.starts[i] = A->stencil.starts[i];
4177: }
4179: PetscLogEventEnd(MAT_Copy, A, B, 0, 0);
4180: PetscObjectStateIncrease((PetscObject)B);
4181: return 0;
4182: }
4184: /*@C
4185: MatConvert - Converts a matrix to another matrix, either of the same
4186: or different type.
4188: Collective
4190: Input Parameters:
4191: + mat - the matrix
4192: . newtype - new matrix type. Use `MATSAME` to create a new matrix of the
4193: same type as the original matrix.
4194: - reuse - denotes if the destination matrix is to be created or reused.
4195: 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
4196: `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).
4198: Output Parameter:
4199: . M - pointer to place new matrix
4201: Level: intermediate
4203: Notes:
4204: `MatConvert()` first creates a new matrix and then copies the data from
4205: the first matrix. A related routine is `MatCopy()`, which copies the matrix
4206: entries of one matrix to another already existing matrix context.
4208: Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4209: the MPI communicator of the generated matrix is always the same as the communicator
4210: of the input matrix.
4212: .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4213: @*/
4214: PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4215: {
4216: PetscBool sametype, issame, flg;
4217: PetscBool3 issymmetric, ishermitian;
4218: char convname[256], mtype[256];
4219: Mat B;
4226: MatCheckPreallocated(mat, 1);
4228: PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg);
4229: if (flg) newtype = mtype;
4231: PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype);
4232: PetscStrcmp(newtype, "same", &issame);
4236: if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4237: PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4238: return 0;
4239: }
4241: /* Cache Mat options because some converters use MatHeaderReplace */
4242: issymmetric = mat->symmetric;
4243: ishermitian = mat->hermitian;
4245: if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4246: PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4247: PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4248: } else {
4249: PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4250: const char *prefix[3] = {"seq", "mpi", ""};
4251: PetscInt i;
4252: /*
4253: Order of precedence:
4254: 0) See if newtype is a superclass of the current matrix.
4255: 1) See if a specialized converter is known to the current matrix.
4256: 2) See if a specialized converter is known to the desired matrix class.
4257: 3) See if a good general converter is registered for the desired class
4258: (as of 6/27/03 only MATMPIADJ falls into this category).
4259: 4) See if a good general converter is known for the current matrix.
4260: 5) Use a really basic converter.
4261: */
4263: /* 0) See if newtype is a superclass of the current matrix.
4264: i.e mat is mpiaij and newtype is aij */
4265: for (i = 0; i < 2; i++) {
4266: PetscStrncpy(convname, prefix[i], sizeof(convname));
4267: PetscStrlcat(convname, newtype, sizeof(convname));
4268: PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg);
4269: PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg);
4270: if (flg) {
4271: if (reuse == MAT_INPLACE_MATRIX) {
4272: PetscInfo(mat, "Early return\n");
4273: return 0;
4274: } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4275: PetscInfo(mat, "Calling MatDuplicate\n");
4276: PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4277: return 0;
4278: } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4279: PetscInfo(mat, "Calling MatCopy\n");
4280: MatCopy(mat, *M, SAME_NONZERO_PATTERN);
4281: return 0;
4282: }
4283: }
4284: }
4285: /* 1) See if a specialized converter is known to the current matrix and the desired class */
4286: for (i = 0; i < 3; i++) {
4287: PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4288: PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4289: PetscStrlcat(convname, "_", sizeof(convname));
4290: PetscStrlcat(convname, prefix[i], sizeof(convname));
4291: PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname));
4292: PetscStrlcat(convname, "_C", sizeof(convname));
4293: PetscObjectQueryFunction((PetscObject)mat, convname, &conv);
4294: PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv);
4295: if (conv) goto foundconv;
4296: }
4298: /* 2) See if a specialized converter is known to the desired matrix class. */
4299: MatCreate(PetscObjectComm((PetscObject)mat), &B);
4300: MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
4301: MatSetType(B, newtype);
4302: for (i = 0; i < 3; i++) {
4303: PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4304: PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4305: PetscStrlcat(convname, "_", sizeof(convname));
4306: PetscStrlcat(convname, prefix[i], sizeof(convname));
4307: PetscStrlcat(convname, newtype, sizeof(convname));
4308: PetscStrlcat(convname, "_C", sizeof(convname));
4309: PetscObjectQueryFunction((PetscObject)B, convname, &conv);
4310: PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv);
4311: if (conv) {
4312: MatDestroy(&B);
4313: goto foundconv;
4314: }
4315: }
4317: /* 3) See if a good general converter is registered for the desired class */
4318: conv = B->ops->convertfrom;
4319: PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv);
4320: MatDestroy(&B);
4321: if (conv) goto foundconv;
4323: /* 4) See if a good general converter is known for the current matrix */
4324: if (mat->ops->convert) conv = mat->ops->convert;
4325: PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv);
4326: if (conv) goto foundconv;
4328: /* 5) Use a really basic converter. */
4329: PetscInfo(mat, "Using MatConvert_Basic\n");
4330: conv = MatConvert_Basic;
4332: foundconv:
4333: PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4334: (*conv)(mat, newtype, reuse, M);
4335: if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4336: /* the block sizes must be same if the mappings are copied over */
4337: (*M)->rmap->bs = mat->rmap->bs;
4338: (*M)->cmap->bs = mat->cmap->bs;
4339: PetscObjectReference((PetscObject)mat->rmap->mapping);
4340: PetscObjectReference((PetscObject)mat->cmap->mapping);
4341: (*M)->rmap->mapping = mat->rmap->mapping;
4342: (*M)->cmap->mapping = mat->cmap->mapping;
4343: }
4344: (*M)->stencil.dim = mat->stencil.dim;
4345: (*M)->stencil.noc = mat->stencil.noc;
4346: for (i = 0; i <= mat->stencil.dim; i++) {
4347: (*M)->stencil.dims[i] = mat->stencil.dims[i];
4348: (*M)->stencil.starts[i] = mat->stencil.starts[i];
4349: }
4350: PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4351: }
4352: PetscObjectStateIncrease((PetscObject)*M);
4354: /* Copy Mat options */
4355: if (issymmetric == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE);
4356: else if (issymmetric == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE);
4357: if (ishermitian == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE);
4358: else if (ishermitian == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE);
4359: return 0;
4360: }
4362: /*@C
4363: MatFactorGetSolverType - Returns name of the package providing the factorization routines
4365: Not Collective
4367: Input Parameter:
4368: . mat - the matrix, must be a factored matrix
4370: Output Parameter:
4371: . type - the string name of the package (do not free this string)
4373: Level: intermediate
4375: Fortran Note:
4376: Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4378: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4379: @*/
4380: PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4381: {
4382: PetscErrorCode (*conv)(Mat, MatSolverType *);
4388: PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv);
4389: if (conv) (*conv)(mat, type);
4390: else *type = MATSOLVERPETSC;
4391: return 0;
4392: }
4394: typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4395: struct _MatSolverTypeForSpecifcType {
4396: MatType mtype;
4397: /* no entry for MAT_FACTOR_NONE */
4398: PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4399: MatSolverTypeForSpecifcType next;
4400: };
4402: typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4403: struct _MatSolverTypeHolder {
4404: char *name;
4405: MatSolverTypeForSpecifcType handlers;
4406: MatSolverTypeHolder next;
4407: };
4409: static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4411: /*@C
4412: MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4414: Input Parameters:
4415: + package - name of the package, for example petsc or superlu
4416: . mtype - the matrix type that works with this package
4417: . ftype - the type of factorization supported by the package
4418: - createfactor - routine that will create the factored matrix ready to be used
4420: Level: developer
4422: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4423: @*/
4424: PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4425: {
4426: MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL;
4427: PetscBool flg;
4428: MatSolverTypeForSpecifcType inext, iprev = NULL;
4430: MatInitializePackage();
4431: if (!next) {
4432: PetscNew(&MatSolverTypeHolders);
4433: PetscStrallocpy(package, &MatSolverTypeHolders->name);
4434: PetscNew(&MatSolverTypeHolders->handlers);
4435: PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype);
4436: MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4437: return 0;
4438: }
4439: while (next) {
4440: PetscStrcasecmp(package, next->name, &flg);
4441: if (flg) {
4443: inext = next->handlers;
4444: while (inext) {
4445: PetscStrcasecmp(mtype, inext->mtype, &flg);
4446: if (flg) {
4447: inext->createfactor[(int)ftype - 1] = createfactor;
4448: return 0;
4449: }
4450: iprev = inext;
4451: inext = inext->next;
4452: }
4453: PetscNew(&iprev->next);
4454: PetscStrallocpy(mtype, (char **)&iprev->next->mtype);
4455: iprev->next->createfactor[(int)ftype - 1] = createfactor;
4456: return 0;
4457: }
4458: prev = next;
4459: next = next->next;
4460: }
4461: PetscNew(&prev->next);
4462: PetscStrallocpy(package, &prev->next->name);
4463: PetscNew(&prev->next->handlers);
4464: PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype);
4465: prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4466: return 0;
4467: }
4469: /*@C
4470: MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4472: Input Parameters:
4473: + type - name of the package, for example petsc or superlu
4474: . ftype - the type of factorization supported by the type
4475: - mtype - the matrix type that works with this type
4477: Output Parameters:
4478: + foundtype - `PETSC_TRUE` if the type was registered
4479: . foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4480: - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4482: Level: developer
4484: .seealso: `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4485: @*/
4486: PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4487: {
4488: MatSolverTypeHolder next = MatSolverTypeHolders;
4489: PetscBool flg;
4490: MatSolverTypeForSpecifcType inext;
4492: if (foundtype) *foundtype = PETSC_FALSE;
4493: if (foundmtype) *foundmtype = PETSC_FALSE;
4494: if (createfactor) *createfactor = NULL;
4496: if (type) {
4497: while (next) {
4498: PetscStrcasecmp(type, next->name, &flg);
4499: if (flg) {
4500: if (foundtype) *foundtype = PETSC_TRUE;
4501: inext = next->handlers;
4502: while (inext) {
4503: PetscStrbeginswith(mtype, inext->mtype, &flg);
4504: if (flg) {
4505: if (foundmtype) *foundmtype = PETSC_TRUE;
4506: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4507: return 0;
4508: }
4509: inext = inext->next;
4510: }
4511: }
4512: next = next->next;
4513: }
4514: } else {
4515: while (next) {
4516: inext = next->handlers;
4517: while (inext) {
4518: PetscStrcmp(mtype, inext->mtype, &flg);
4519: if (flg && inext->createfactor[(int)ftype - 1]) {
4520: if (foundtype) *foundtype = PETSC_TRUE;
4521: if (foundmtype) *foundmtype = PETSC_TRUE;
4522: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4523: return 0;
4524: }
4525: inext = inext->next;
4526: }
4527: next = next->next;
4528: }
4529: /* try with base classes inext->mtype */
4530: next = MatSolverTypeHolders;
4531: while (next) {
4532: inext = next->handlers;
4533: while (inext) {
4534: PetscStrbeginswith(mtype, inext->mtype, &flg);
4535: if (flg && inext->createfactor[(int)ftype - 1]) {
4536: if (foundtype) *foundtype = PETSC_TRUE;
4537: if (foundmtype) *foundmtype = PETSC_TRUE;
4538: if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4539: return 0;
4540: }
4541: inext = inext->next;
4542: }
4543: next = next->next;
4544: }
4545: }
4546: return 0;
4547: }
4549: PetscErrorCode MatSolverTypeDestroy(void)
4550: {
4551: MatSolverTypeHolder next = MatSolverTypeHolders, prev;
4552: MatSolverTypeForSpecifcType inext, iprev;
4554: while (next) {
4555: PetscFree(next->name);
4556: inext = next->handlers;
4557: while (inext) {
4558: PetscFree(inext->mtype);
4559: iprev = inext;
4560: inext = inext->next;
4561: PetscFree(iprev);
4562: }
4563: prev = next;
4564: next = next->next;
4565: PetscFree(prev);
4566: }
4567: MatSolverTypeHolders = NULL;
4568: return 0;
4569: }
4571: /*@C
4572: MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4574: Logically Collective
4576: Input Parameters:
4577: . mat - the matrix
4579: Output Parameters:
4580: . flg - `PETSC_TRUE` if uses the ordering
4582: Level: developer
4584: Note:
4585: Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4586: packages do not, thus we want to skip generating the ordering when it is not needed or used.
4588: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4589: @*/
4590: PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4591: {
4592: *flg = mat->canuseordering;
4593: return 0;
4594: }
4596: /*@C
4597: MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4599: Logically Collective
4601: Input Parameters:
4602: . mat - the matrix obtained with `MatGetFactor()`
4604: Output Parameters:
4605: . otype - the preferred type
4607: Level: developer
4609: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4610: @*/
4611: PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4612: {
4613: *otype = mat->preferredordering[ftype];
4615: return 0;
4616: }
4618: /*@C
4619: MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4621: Collective
4623: Input Parameters:
4624: + mat - the matrix
4625: . type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4626: - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4628: Output Parameters:
4629: . f - the factor matrix used with MatXXFactorSymbolic() calls
4631: Options Database Key:
4632: . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4633: One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4635: Level: intermediate
4637: Notes:
4638: Users usually access the factorization solvers via `KSP`
4640: Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4641: such as pastix, superlu, mumps etc.
4643: PETSc must have been ./configure to use the external solver, using the option --download-package
4645: Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4646: where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4647: call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix.
4649: Developer Note:
4650: This should actually be called `MatCreateFactor()` since it creates a new factor object
4652: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4653: `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4654: @*/
4655: PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4656: {
4657: PetscBool foundtype, foundmtype;
4658: PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4664: MatCheckPreallocated(mat, 1);
4666: MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv);
4667: if (!foundtype) {
4668: if (type) {
4669: 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],
4670: ((PetscObject)mat)->type_name, type);
4671: } else {
4672: 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);
4673: }
4674: }
4678: (*conv)(mat, ftype, f);
4679: if (mat->factorprefix) MatSetOptionsPrefix(*f, mat->factorprefix);
4680: return 0;
4681: }
4683: /*@C
4684: MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4686: Not Collective
4688: Input Parameters:
4689: + mat - the matrix
4690: . type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4691: - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4693: Output Parameter:
4694: . flg - PETSC_TRUE if the factorization is available
4696: Level: intermediate
4698: Notes:
4699: Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4700: such as pastix, superlu, mumps etc.
4702: PETSc must have been ./configure to use the external solver, using the option --download-package
4704: Developer Note:
4705: This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4707: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4708: `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4709: @*/
4710: PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4711: {
4712: PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4719: MatCheckPreallocated(mat, 1);
4721: MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv);
4722: *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4723: return 0;
4724: }
4726: /*@
4727: MatDuplicate - Duplicates a matrix including the non-zero structure.
4729: Collective
4731: Input Parameters:
4732: + mat - the matrix
4733: - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4734: See the manual page for `MatDuplicateOption()` for an explanation of these options.
4736: Output Parameter:
4737: . M - pointer to place new matrix
4739: Level: intermediate
4741: Notes:
4742: You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4744: 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.
4746: 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
4747: is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4748: User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4750: .seealso: `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4751: @*/
4752: PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4753: {
4754: Mat B;
4755: VecType vtype;
4756: PetscInt i;
4757: PetscObject dm;
4758: void (*viewf)(void);
4765: MatCheckPreallocated(mat, 1);
4767: *M = NULL;
4768: PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4769: PetscUseTypeMethod(mat, duplicate, op, M);
4770: PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4771: B = *M;
4773: MatGetOperation(mat, MATOP_VIEW, &viewf);
4774: if (viewf) MatSetOperation(B, MATOP_VIEW, viewf);
4775: MatGetVecType(mat, &vtype);
4776: MatSetVecType(B, vtype);
4778: B->stencil.dim = mat->stencil.dim;
4779: B->stencil.noc = mat->stencil.noc;
4780: for (i = 0; i <= mat->stencil.dim; i++) {
4781: B->stencil.dims[i] = mat->stencil.dims[i];
4782: B->stencil.starts[i] = mat->stencil.starts[i];
4783: }
4785: B->nooffproczerorows = mat->nooffproczerorows;
4786: B->nooffprocentries = mat->nooffprocentries;
4788: PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm);
4789: if (dm) PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm);
4790: PetscObjectStateIncrease((PetscObject)B);
4791: return 0;
4792: }
4794: /*@
4795: MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4797: Logically Collective
4799: Input Parameters:
4800: + mat - the matrix
4801: - v - the vector for storing the diagonal
4803: Output Parameter:
4804: . v - the diagonal of the matrix
4806: Level: intermediate
4808: Note:
4809: Currently only correct in parallel for square matrices.
4811: .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4812: @*/
4813: PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4814: {
4819: MatCheckPreallocated(mat, 1);
4821: PetscUseTypeMethod(mat, getdiagonal, v);
4822: PetscObjectStateIncrease((PetscObject)v);
4823: return 0;
4824: }
4826: /*@C
4827: MatGetRowMin - Gets the minimum value (of the real part) of each
4828: row of the matrix
4830: Logically Collective
4832: Input Parameter:
4833: . mat - the matrix
4835: Output Parameters:
4836: + v - the vector for storing the maximums
4837: - idx - the indices of the column found for each row (optional)
4839: Level: intermediate
4841: Note:
4842: The result of this call are the same as if one converted the matrix to dense format
4843: and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4845: This code is only implemented for a couple of matrix formats.
4847: .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4848: `MatGetRowMax()`
4849: @*/
4850: PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4851: {
4857: if (!mat->cmap->N) {
4858: VecSet(v, PETSC_MAX_REAL);
4859: if (idx) {
4860: PetscInt i, m = mat->rmap->n;
4861: for (i = 0; i < m; i++) idx[i] = -1;
4862: }
4863: } else {
4864: MatCheckPreallocated(mat, 1);
4865: }
4866: PetscUseTypeMethod(mat, getrowmin, v, idx);
4867: PetscObjectStateIncrease((PetscObject)v);
4868: return 0;
4869: }
4871: /*@C
4872: MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4873: row of the matrix
4875: Logically Collective
4877: Input Parameter:
4878: . mat - the matrix
4880: Output Parameters:
4881: + v - the vector for storing the minimums
4882: - idx - the indices of the column found for each row (or `NULL` if not needed)
4884: Level: intermediate
4886: Notes:
4887: if a row is completely empty or has only 0.0 values then the idx[] value for that
4888: row is 0 (the first column).
4890: This code is only implemented for a couple of matrix formats.
4892: .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4893: @*/
4894: PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4895: {
4902: if (!mat->cmap->N) {
4903: VecSet(v, 0.0);
4904: if (idx) {
4905: PetscInt i, m = mat->rmap->n;
4906: for (i = 0; i < m; i++) idx[i] = -1;
4907: }
4908: } else {
4909: MatCheckPreallocated(mat, 1);
4910: if (idx) PetscArrayzero(idx, mat->rmap->n);
4911: PetscUseTypeMethod(mat, getrowminabs, v, idx);
4912: }
4913: PetscObjectStateIncrease((PetscObject)v);
4914: return 0;
4915: }
4917: /*@C
4918: MatGetRowMax - Gets the maximum value (of the real part) of each
4919: row of the matrix
4921: Logically Collective
4923: Input Parameter:
4924: . mat - the matrix
4926: Output Parameters:
4927: + v - the vector for storing the maximums
4928: - idx - the indices of the column found for each row (optional)
4930: Level: intermediate
4932: Notes:
4933: The result of this call are the same as if one converted the matrix to dense format
4934: and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4936: This code is only implemented for a couple of matrix formats.
4938: .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4939: @*/
4940: PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
4941: {
4947: if (!mat->cmap->N) {
4948: VecSet(v, PETSC_MIN_REAL);
4949: if (idx) {
4950: PetscInt i, m = mat->rmap->n;
4951: for (i = 0; i < m; i++) idx[i] = -1;
4952: }
4953: } else {
4954: MatCheckPreallocated(mat, 1);
4955: PetscUseTypeMethod(mat, getrowmax, v, idx);
4956: }
4957: PetscObjectStateIncrease((PetscObject)v);
4958: return 0;
4959: }
4961: /*@C
4962: MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4963: row of the matrix
4965: Logically Collective
4967: Input Parameter:
4968: . mat - the matrix
4970: Output Parameters:
4971: + v - the vector for storing the maximums
4972: - idx - the indices of the column found for each row (or `NULL` if not needed)
4974: Level: intermediate
4976: Notes:
4977: if a row is completely empty or has only 0.0 values then the idx[] value for that
4978: row is 0 (the first column).
4980: This code is only implemented for a couple of matrix formats.
4982: .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4983: @*/
4984: PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
4985: {
4991: if (!mat->cmap->N) {
4992: VecSet(v, 0.0);
4993: if (idx) {
4994: PetscInt i, m = mat->rmap->n;
4995: for (i = 0; i < m; i++) idx[i] = -1;
4996: }
4997: } else {
4998: MatCheckPreallocated(mat, 1);
4999: if (idx) PetscArrayzero(idx, mat->rmap->n);
5000: PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5001: }
5002: PetscObjectStateIncrease((PetscObject)v);
5003: return 0;
5004: }
5006: /*@
5007: MatGetRowSum - Gets the sum of each row of the matrix
5009: Logically or Neighborhood Collective
5011: Input Parameters:
5012: . mat - the matrix
5014: Output Parameter:
5015: . v - the vector for storing the sum of rows
5017: Level: intermediate
5019: Notes:
5020: This code is slow since it is not currently specialized for different formats
5022: .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5023: @*/
5024: PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5025: {
5026: Vec ones;
5032: MatCheckPreallocated(mat, 1);
5033: MatCreateVecs(mat, &ones, NULL);
5034: VecSet(ones, 1.);
5035: MatMult(mat, ones, v);
5036: VecDestroy(&ones);
5037: return 0;
5038: }
5040: /*@
5041: MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5042: when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5044: Collective
5046: Input Parameter:
5047: . mat - the matrix to provide the transpose
5049: Output Parameter:
5050: . 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
5052: Level: advanced
5054: Note:
5055: 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
5056: routine allows bypassing that call.
5058: .seealso: `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5059: @*/
5060: PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5061: {
5062: PetscContainer rB = NULL;
5063: MatParentState *rb = NULL;
5065: PetscNew(&rb);
5066: rb->id = ((PetscObject)mat)->id;
5067: rb->state = 0;
5068: MatGetNonzeroState(mat, &rb->nonzerostate);
5069: PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB);
5070: PetscContainerSetPointer(rB, rb);
5071: PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault);
5072: PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB);
5073: PetscObjectDereference((PetscObject)rB);
5074: return 0;
5075: }
5077: /*@
5078: MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5080: Collective
5082: Input Parameters:
5083: + mat - the matrix to transpose
5084: - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5086: Output Parameter:
5087: . B - the transpose
5089: Level: intermediate
5091: Notes:
5092: If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5094: `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
5095: transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5097: 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.
5099: Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5101: If mat is unchanged from the last call this function returns immediately without recomputing the result
5103: If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5105: .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5106: `MatTransposeSymbolic()`
5107: @*/
5108: PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5109: {
5110: PetscContainer rB = NULL;
5111: MatParentState *rb = NULL;
5119: MatCheckPreallocated(mat, 1);
5120: if (reuse == MAT_REUSE_MATRIX) {
5121: PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5123: PetscContainerGetPointer(rB, (void **)&rb);
5125: if (rb->state == ((PetscObject)mat)->state) return 0;
5126: }
5128: PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0);
5129: if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5130: PetscUseTypeMethod(mat, transpose, reuse, B);
5131: PetscObjectStateIncrease((PetscObject)*B);
5132: }
5133: PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0);
5135: if (reuse == MAT_INITIAL_MATRIX) MatTransposeSetPrecursor(mat, *B);
5136: if (reuse != MAT_INPLACE_MATRIX) {
5137: PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5138: PetscContainerGetPointer(rB, (void **)&rb);
5139: rb->state = ((PetscObject)mat)->state;
5140: rb->nonzerostate = mat->nonzerostate;
5141: }
5142: return 0;
5143: }
5145: /*@
5146: MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5148: Collective
5150: Input Parameters:
5151: . A - the matrix to transpose
5153: Output Parameter:
5154: . 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
5155: numerical portion.
5157: Level: intermediate
5159: Note:
5160: This is not supported for many matrix types, use `MatTranspose()` in those cases
5162: .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5163: @*/
5164: PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5165: {
5171: PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0);
5172: (*A->ops->transposesymbolic)(A, B);
5173: PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0);
5175: MatTransposeSetPrecursor(A, *B);
5176: return 0;
5177: }
5179: PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5180: {
5181: PetscContainer rB;
5182: MatParentState *rb;
5188: PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB);
5190: PetscContainerGetPointer(rB, (void **)&rb);
5193: return 0;
5194: }
5196: /*@
5197: MatIsTranspose - Test whether a matrix is another one's transpose,
5198: or its own, in which case it tests symmetry.
5200: Collective
5202: Input Parameters:
5203: + A - the matrix to test
5204: - B - the matrix to test against, this can equal the first parameter
5206: Output Parameters:
5207: . flg - the result
5209: Level: intermediate
5211: Notes:
5212: Only available for `MATAIJ` matrices.
5214: The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5215: test involves parallel copies of the block-offdiagonal parts of the matrix.
5217: .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5218: @*/
5219: PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5220: {
5221: PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5226: PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f);
5227: PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g);
5228: *flg = PETSC_FALSE;
5229: if (f && g) {
5231: (*f)(A, B, tol, flg);
5232: } else {
5233: MatType mattype;
5235: MatGetType(f ? B : A, &mattype);
5236: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5237: }
5238: return 0;
5239: }
5241: /*@
5242: MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5244: Collective
5246: Input Parameters:
5247: + mat - the matrix to transpose and complex conjugate
5248: - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5250: Output Parameter:
5251: . B - the Hermitian transpose
5253: Level: intermediate
5255: .seealso: `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5256: @*/
5257: PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5258: {
5259: MatTranspose(mat, reuse, B);
5260: #if defined(PETSC_USE_COMPLEX)
5261: MatConjugate(*B);
5262: #endif
5263: return 0;
5264: }
5266: /*@
5267: MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5269: Collective
5271: Input Parameters:
5272: + A - the matrix to test
5273: - B - the matrix to test against, this can equal the first parameter
5275: Output Parameters:
5276: . flg - the result
5278: Level: intermediate
5280: Notes:
5281: Only available for `MATAIJ` matrices.
5283: The sequential algorithm
5284: has a running time of the order of the number of nonzeros; the parallel
5285: test involves parallel copies of the block-offdiagonal parts of the matrix.
5287: .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5288: @*/
5289: PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5290: {
5291: PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5296: PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f);
5297: PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g);
5298: if (f && g) {
5300: (*f)(A, B, tol, flg);
5301: }
5302: return 0;
5303: }
5305: /*@
5306: MatPermute - Creates a new matrix with rows and columns permuted from the
5307: original.
5309: Collective
5311: Input Parameters:
5312: + mat - the matrix to permute
5313: . row - row permutation, each processor supplies only the permutation for its rows
5314: - col - column permutation, each processor supplies only the permutation for its columns
5316: Output Parameters:
5317: . B - the permuted matrix
5319: Level: advanced
5321: Note:
5322: The index sets map from row/col of permuted matrix to row/col of original matrix.
5323: The index sets should be on the same communicator as mat and have the same local sizes.
5325: Developer Note:
5326: If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5327: exploit the fact that row and col are permutations, consider implementing the
5328: more general `MatCreateSubMatrix()` instead.
5330: .seealso: `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5331: @*/
5332: PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5333: {
5344: MatCheckPreallocated(mat, 1);
5346: if (mat->ops->permute) {
5347: PetscUseTypeMethod(mat, permute, row, col, B);
5348: PetscObjectStateIncrease((PetscObject)*B);
5349: } else {
5350: MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B);
5351: }
5352: return 0;
5353: }
5355: /*@
5356: MatEqual - Compares two matrices.
5358: Collective
5360: Input Parameters:
5361: + A - the first matrix
5362: - B - the second matrix
5364: Output Parameter:
5365: . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5367: Level: intermediate
5369: .seealso: `Mat`
5370: @*/
5371: PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5372: {
5379: MatCheckPreallocated(A, 1);
5380: MatCheckPreallocated(B, 2);
5384: B->cmap->N);
5385: if (A->ops->equal && A->ops->equal == B->ops->equal) {
5386: PetscUseTypeMethod(A, equal, B, flg);
5387: } else {
5388: MatMultEqual(A, B, 10, flg);
5389: }
5390: return 0;
5391: }
5393: /*@
5394: MatDiagonalScale - Scales a matrix on the left and right by diagonal
5395: matrices that are stored as vectors. Either of the two scaling
5396: matrices can be `NULL`.
5398: Collective
5400: Input Parameters:
5401: + mat - the matrix to be scaled
5402: . l - the left scaling vector (or `NULL`)
5403: - r - the right scaling vector (or `NULL`)
5405: Level: intermediate
5407: Note:
5408: `MatDiagonalScale()` computes A = LAR, where
5409: L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5410: The L scales the rows of the matrix, the R scales the columns of the matrix.
5412: .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5413: @*/
5414: PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5415: {
5418: if (l) {
5421: }
5422: if (r) {
5425: }
5428: MatCheckPreallocated(mat, 1);
5429: if (!l && !r) return 0;
5431: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5432: PetscUseTypeMethod(mat, diagonalscale, l, r);
5433: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5434: PetscObjectStateIncrease((PetscObject)mat);
5435: if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5436: return 0;
5437: }
5439: /*@
5440: MatScale - Scales all elements of a matrix by a given number.
5442: Logically Collective
5444: Input Parameters:
5445: + mat - the matrix to be scaled
5446: - a - the scaling value
5448: Output Parameter:
5449: . mat - the scaled matrix
5451: Level: intermediate
5453: .seealso: `Mat`, `MatDiagonalScale()`
5454: @*/
5455: PetscErrorCode MatScale(Mat mat, PetscScalar a)
5456: {
5463: MatCheckPreallocated(mat, 1);
5465: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5466: if (a != (PetscScalar)1.0) {
5467: PetscUseTypeMethod(mat, scale, a);
5468: PetscObjectStateIncrease((PetscObject)mat);
5469: }
5470: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5471: return 0;
5472: }
5474: /*@
5475: MatNorm - Calculates various norms of a matrix.
5477: Collective
5479: Input Parameters:
5480: + mat - the matrix
5481: - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5483: Output Parameter:
5484: . nrm - the resulting norm
5486: Level: intermediate
5488: .seealso: `Mat`
5489: @*/
5490: PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5491: {
5498: MatCheckPreallocated(mat, 1);
5500: PetscUseTypeMethod(mat, norm, type, nrm);
5501: return 0;
5502: }
5504: /*
5505: This variable is used to prevent counting of MatAssemblyBegin() that
5506: are called from within a MatAssemblyEnd().
5507: */
5508: static PetscInt MatAssemblyEnd_InUse = 0;
5509: /*@
5510: MatAssemblyBegin - Begins assembling the matrix. This routine should
5511: be called after completing all calls to `MatSetValues()`.
5513: Collective
5515: Input Parameters:
5516: + mat - the matrix
5517: - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5519: Level: beginner
5521: Notes:
5522: `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to
5523: use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5525: Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5526: in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5527: using the matrix.
5529: ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5530: 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
5531: a global collective operation requiring all processes that share the matrix.
5533: Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5534: out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5535: before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5537: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5538: @*/
5539: PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5540: {
5543: MatCheckPreallocated(mat, 1);
5545: if (mat->assembled) {
5546: mat->was_assembled = PETSC_TRUE;
5547: mat->assembled = PETSC_FALSE;
5548: }
5550: if (!MatAssemblyEnd_InUse) {
5551: PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0);
5552: PetscTryTypeMethod(mat, assemblybegin, type);
5553: PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0);
5554: } else PetscTryTypeMethod(mat, assemblybegin, type);
5555: return 0;
5556: }
5558: /*@
5559: MatAssembled - Indicates if a matrix has been assembled and is ready for
5560: use; for example, in matrix-vector product.
5562: Not Collective
5564: Input Parameter:
5565: . mat - the matrix
5567: Output Parameter:
5568: . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5570: Level: advanced
5572: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5573: @*/
5574: PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5575: {
5578: *assembled = mat->assembled;
5579: return 0;
5580: }
5582: /*@
5583: MatAssemblyEnd - Completes assembling the matrix. This routine should
5584: be called after `MatAssemblyBegin()`.
5586: Collective on Mat
5588: Input Parameters:
5589: + mat - the matrix
5590: - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5592: Options Database Keys:
5593: + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5594: . -mat_view ::ascii_info_detail - Prints more detailed info
5595: . -mat_view - Prints matrix in ASCII format
5596: . -mat_view ::ascii_matlab - Prints matrix in Matlab format
5597: . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5598: . -display <name> - Sets display name (default is host)
5599: . -draw_pause <sec> - Sets number of seconds to pause after display
5600: . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5601: . -viewer_socket_machine <machine> - Machine to use for socket
5602: . -viewer_socket_port <port> - Port number to use for socket
5603: - -mat_view binary:filename[:append] - Save matrix to file in binary format
5605: Level: beginner
5607: .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5608: @*/
5609: PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5610: {
5611: static PetscInt inassm = 0;
5612: PetscBool flg = PETSC_FALSE;
5617: inassm++;
5618: MatAssemblyEnd_InUse++;
5619: if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5620: PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0);
5621: PetscTryTypeMethod(mat, assemblyend, type);
5622: PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0);
5623: } else PetscTryTypeMethod(mat, assemblyend, type);
5625: /* Flush assembly is not a true assembly */
5626: if (type != MAT_FLUSH_ASSEMBLY) {
5627: if (mat->num_ass) {
5628: if (!mat->symmetry_eternal) {
5629: mat->symmetric = PETSC_BOOL3_UNKNOWN;
5630: mat->hermitian = PETSC_BOOL3_UNKNOWN;
5631: }
5632: if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5633: if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5634: }
5635: mat->num_ass++;
5636: mat->assembled = PETSC_TRUE;
5637: mat->ass_nonzerostate = mat->nonzerostate;
5638: }
5640: mat->insertmode = NOT_SET_VALUES;
5641: MatAssemblyEnd_InUse--;
5642: PetscObjectStateIncrease((PetscObject)mat);
5643: if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5644: MatViewFromOptions(mat, NULL, "-mat_view");
5646: if (mat->checksymmetryonassembly) {
5647: MatIsSymmetric(mat, mat->checksymmetrytol, &flg);
5648: if (flg) {
5649: PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5650: } else {
5651: PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5652: }
5653: }
5654: if (mat->nullsp && mat->checknullspaceonassembly) MatNullSpaceTest(mat->nullsp, mat, NULL);
5655: }
5656: inassm--;
5657: return 0;
5658: }
5660: /*@
5661: MatSetOption - Sets a parameter option for a matrix. Some options
5662: may be specific to certain storage formats. Some options
5663: determine how values will be inserted (or added). Sorted,
5664: row-oriented input will generally assemble the fastest. The default
5665: is row-oriented.
5667: Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5669: Input Parameters:
5670: + mat - the matrix
5671: . option - the option, one of those listed below (and possibly others),
5672: - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5674: Options Describing Matrix Structure:
5675: + `MAT_SPD` - symmetric positive definite
5676: . `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5677: . `MAT_HERMITIAN` - transpose is the complex conjugation
5678: . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5679: . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5680: . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5681: - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5683: These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5684: do not need to be computed (usually at a high cost)
5686: Options For Use with `MatSetValues()`:
5687: Insert a logically dense subblock, which can be
5688: . `MAT_ROW_ORIENTED` - row-oriented (default)
5690: Note these options reflect the data you pass in with `MatSetValues()`; it has
5691: nothing to do with how the data is stored internally in the matrix
5692: data structure.
5694: When (re)assembling a matrix, we can restrict the input for
5695: efficiency/debugging purposes. These options include
5696: + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5697: . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5698: . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5699: . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5700: . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5701: . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5702: any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5703: performance for very large process counts.
5704: - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5705: of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5706: functions, instead sending only neighbor messages.
5708: Level: intermediate
5710: Notes:
5711: Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5713: Some options are relevant only for particular matrix types and
5714: are thus ignored by others. Other options are not supported by
5715: certain matrix types and will generate an error message if set.
5717: If using Fortran to compute a matrix, one may need to
5718: use the column-oriented option (or convert to the row-oriented
5719: format).
5721: `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5722: that would generate a new entry in the nonzero structure is instead
5723: ignored. Thus, if memory has not already been allocated for this particular
5724: data, then the insertion is ignored. For dense matrices, in which
5725: the entire array is allocated, no entries are ever ignored.
5726: Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5728: `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5729: that would generate a new entry in the nonzero structure instead produces
5730: 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
5732: `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5733: that would generate a new entry that has not been preallocated will
5734: instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5735: only.) This is a useful flag when debugging matrix memory preallocation.
5736: If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5738: `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5739: other processors should be dropped, rather than stashed.
5740: This is useful if you know that the "owning" processor is also
5741: always generating the correct matrix entries, so that PETSc need
5742: not transfer duplicate entries generated on another processor.
5744: `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5745: searches during matrix assembly. When this flag is set, the hash table
5746: is created during the first matrix assembly. This hash table is
5747: used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5748: to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5749: should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5750: supported by `MATMPIBAIJ` format only.
5752: `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5753: are kept in the nonzero structure
5755: `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5756: a zero location in the matrix
5758: `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5760: `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5761: zero row routines and thus improves performance for very large process counts.
5763: `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5764: part of the matrix (since they should match the upper triangular part).
5766: `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5767: single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5768: with finite difference schemes with non-periodic boundary conditions.
5770: Developer Note:
5771: `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5772: places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5773: to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5774: not changed.
5776: .seealso: `MatOption`, `Mat`, `MatGetOption()`
5777: @*/
5778: PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5779: {
5781: if (op > 0) {
5784: }
5788: switch (op) {
5789: case MAT_FORCE_DIAGONAL_ENTRIES:
5790: mat->force_diagonals = flg;
5791: return 0;
5792: case MAT_NO_OFF_PROC_ENTRIES:
5793: mat->nooffprocentries = flg;
5794: return 0;
5795: case MAT_SUBSET_OFF_PROC_ENTRIES:
5796: mat->assembly_subset = flg;
5797: if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5798: #if !defined(PETSC_HAVE_MPIUNI)
5799: MatStashScatterDestroy_BTS(&mat->stash);
5800: #endif
5801: mat->stash.first_assembly_done = PETSC_FALSE;
5802: }
5803: return 0;
5804: case MAT_NO_OFF_PROC_ZERO_ROWS:
5805: mat->nooffproczerorows = flg;
5806: return 0;
5807: case MAT_SPD:
5808: if (flg) {
5809: mat->spd = PETSC_BOOL3_TRUE;
5810: mat->symmetric = PETSC_BOOL3_TRUE;
5811: mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5812: } else {
5813: mat->spd = PETSC_BOOL3_FALSE;
5814: }
5815: break;
5816: case MAT_SYMMETRIC:
5817: mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5818: if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5819: #if !defined(PETSC_USE_COMPLEX)
5820: mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5821: #endif
5822: break;
5823: case MAT_HERMITIAN:
5824: mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5825: if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5826: #if !defined(PETSC_USE_COMPLEX)
5827: mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5828: #endif
5829: break;
5830: case MAT_STRUCTURALLY_SYMMETRIC:
5831: mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5832: break;
5833: case MAT_SYMMETRY_ETERNAL:
5835: mat->symmetry_eternal = flg;
5836: if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5837: break;
5838: case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5840: mat->structural_symmetry_eternal = flg;
5841: break;
5842: case MAT_SPD_ETERNAL:
5844: mat->spd_eternal = flg;
5845: if (flg) {
5846: mat->structural_symmetry_eternal = PETSC_TRUE;
5847: mat->symmetry_eternal = PETSC_TRUE;
5848: }
5849: break;
5850: case MAT_STRUCTURE_ONLY:
5851: mat->structure_only = flg;
5852: break;
5853: case MAT_SORTED_FULL:
5854: mat->sortedfull = flg;
5855: break;
5856: default:
5857: break;
5858: }
5859: PetscTryTypeMethod(mat, setoption, op, flg);
5860: return 0;
5861: }
5863: /*@
5864: MatGetOption - Gets a parameter option that has been set for a matrix.
5866: Logically Collective
5868: Input Parameters:
5869: + mat - the matrix
5870: - option - the option, this only responds to certain options, check the code for which ones
5872: Output Parameter:
5873: . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5875: Level: intermediate
5877: Notes:
5878: Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5880: Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5881: `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5883: .seealso: `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5884: `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5885: @*/
5886: PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5887: {
5894: switch (op) {
5895: case MAT_NO_OFF_PROC_ENTRIES:
5896: *flg = mat->nooffprocentries;
5897: break;
5898: case MAT_NO_OFF_PROC_ZERO_ROWS:
5899: *flg = mat->nooffproczerorows;
5900: break;
5901: case MAT_SYMMETRIC:
5902: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5903: break;
5904: case MAT_HERMITIAN:
5905: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5906: break;
5907: case MAT_STRUCTURALLY_SYMMETRIC:
5908: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5909: break;
5910: case MAT_SPD:
5911: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
5912: break;
5913: case MAT_SYMMETRY_ETERNAL:
5914: *flg = mat->symmetry_eternal;
5915: break;
5916: case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5917: *flg = mat->symmetry_eternal;
5918: break;
5919: default:
5920: break;
5921: }
5922: return 0;
5923: }
5925: /*@
5926: MatZeroEntries - Zeros all entries of a matrix. For sparse matrices
5927: this routine retains the old nonzero structure.
5929: Logically Collective
5931: Input Parameters:
5932: . mat - the matrix
5934: Level: intermediate
5936: Note:
5937: 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.
5938: See the Performance chapter of the users manual for information on preallocating matrices.
5940: .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
5941: @*/
5942: PetscErrorCode MatZeroEntries(Mat mat)
5943: {
5948: MatCheckPreallocated(mat, 1);
5950: PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0);
5951: PetscUseTypeMethod(mat, zeroentries);
5952: PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0);
5953: PetscObjectStateIncrease((PetscObject)mat);
5954: return 0;
5955: }
5957: /*@
5958: MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5959: of a set of rows and columns of a matrix.
5961: Collective
5963: Input Parameters:
5964: + mat - the matrix
5965: . numRows - the number of rows/columns to zero
5966: . rows - the global row indices
5967: . diag - value put in the diagonal of the eliminated rows
5968: . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
5969: - b - optional vector of the right hand side, that will be adjusted by provided solution entries
5971: Level: intermediate
5973: Notes:
5974: This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5976: For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
5977: 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
5979: If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5980: Krylov method to take advantage of the known solution on the zeroed rows.
5982: For the parallel case, all processes that share the matrix (i.e.,
5983: those in the communicator used for matrix creation) MUST call this
5984: routine, regardless of whether any rows being zeroed are owned by
5985: them.
5987: Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5989: Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5990: list only rows local to itself).
5992: The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
5994: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5995: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5996: @*/
5997: PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
5998: {
6004: MatCheckPreallocated(mat, 1);
6006: PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6007: MatViewFromOptions(mat, NULL, "-mat_view");
6008: PetscObjectStateIncrease((PetscObject)mat);
6009: return 0;
6010: }
6012: /*@
6013: MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6014: of a set of rows and columns of a matrix.
6016: Collective
6018: Input Parameters:
6019: + mat - the matrix
6020: . is - the rows to zero
6021: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6022: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6023: - b - optional vector of right hand side, that will be adjusted by provided solution
6025: Level: intermediate
6027: Note:
6028: See `MatZeroRowsColumns()` for details on how this routine operates.
6030: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6031: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6032: @*/
6033: PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6034: {
6035: PetscInt numRows;
6036: const PetscInt *rows;
6042: ISGetLocalSize(is, &numRows);
6043: ISGetIndices(is, &rows);
6044: MatZeroRowsColumns(mat, numRows, rows, diag, x, b);
6045: ISRestoreIndices(is, &rows);
6046: return 0;
6047: }
6049: /*@
6050: MatZeroRows - Zeros all entries (except possibly the main diagonal)
6051: of a set of rows of a matrix.
6053: Collective
6055: Input Parameters:
6056: + mat - the matrix
6057: . numRows - the number of rows to zero
6058: . rows - the global row indices
6059: . diag - value put in the diagonal of the zeroed rows
6060: . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6061: - b - optional vector of right hand side, that will be adjusted by provided solution entries
6063: Level: intermediate
6065: Notes:
6066: This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6068: For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6070: If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6071: Krylov method to take advantage of the known solution on the zeroed rows.
6073: May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reduced problem (`PCDISTRIBUTE` completely eliminates the zeroed rows and their corresponding columns)
6074: from the matrix.
6076: Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6077: 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
6078: formats this does not alter the nonzero structure.
6080: If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6081: of the matrix is not changed the values are
6082: merely zeroed.
6084: The user can set a value in the diagonal entry (or for the `MATAIJ` format
6085: formats can optionally remove the main diagonal entry from the
6086: nonzero structure as well, by passing 0.0 as the final argument).
6088: For the parallel case, all processes that share the matrix (i.e.,
6089: those in the communicator used for matrix creation) MUST call this
6090: routine, regardless of whether any rows being zeroed are owned by
6091: them.
6093: Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6094: list only rows local to itself).
6096: You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6097: owns that are to be zeroed. This saves a global synchronization in the implementation.
6099: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6100: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6101: @*/
6102: PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6103: {
6109: MatCheckPreallocated(mat, 1);
6111: PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6112: MatViewFromOptions(mat, NULL, "-mat_view");
6113: PetscObjectStateIncrease((PetscObject)mat);
6114: return 0;
6115: }
6117: /*@
6118: MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6119: of a set of rows of a matrix.
6121: Collective on Mat
6123: Input Parameters:
6124: + mat - the matrix
6125: . is - index set of rows to remove (if `NULL` then no row is removed)
6126: . diag - value put in all diagonals of eliminated rows
6127: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6128: - b - optional vector of right hand side, that will be adjusted by provided solution
6130: Level: intermediate
6132: Note:
6133: See `MatZeroRows()` for details on how this routine operates.
6135: .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6136: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6137: @*/
6138: PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6139: {
6140: PetscInt numRows = 0;
6141: const PetscInt *rows = NULL;
6145: if (is) {
6147: ISGetLocalSize(is, &numRows);
6148: ISGetIndices(is, &rows);
6149: }
6150: MatZeroRows(mat, numRows, rows, diag, x, b);
6151: if (is) ISRestoreIndices(is, &rows);
6152: return 0;
6153: }
6155: /*@
6156: MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6157: of a set of rows of a matrix. These rows must be local to the process.
6159: Collective
6161: Input Parameters:
6162: + mat - the matrix
6163: . numRows - the number of rows to remove
6164: . rows - the grid coordinates (and component number when dof > 1) for matrix rows
6165: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6166: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6167: - b - optional vector of right hand side, that will be adjusted by provided solution
6169: Level: intermediate
6171: Notes:
6172: See `MatZeroRows()` for details on how this routine operates.
6174: The grid coordinates are across the entire grid, not just the local portion
6176: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6177: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6178: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6179: `DM_BOUNDARY_PERIODIC` boundary type.
6181: 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
6182: a single value per point) you can skip filling those indices.
6184: Fortran Note:
6185: idxm and idxn should be declared as
6186: $ MatStencil idxm(4,m)
6187: and the values inserted using
6188: .vb
6189: idxm(MatStencil_i,1) = i
6190: idxm(MatStencil_j,1) = j
6191: idxm(MatStencil_k,1) = k
6192: idxm(MatStencil_c,1) = c
6193: etc
6194: .ve
6196: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6197: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6198: @*/
6199: PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6200: {
6201: PetscInt dim = mat->stencil.dim;
6202: PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc);
6203: PetscInt *dims = mat->stencil.dims + 1;
6204: PetscInt *starts = mat->stencil.starts;
6205: PetscInt *dxm = (PetscInt *)rows;
6206: PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6212: PetscMalloc1(numRows, &jdxm);
6213: for (i = 0; i < numRows; ++i) {
6214: /* Skip unused dimensions (they are ordered k, j, i, c) */
6215: for (j = 0; j < 3 - sdim; ++j) dxm++;
6216: /* Local index in X dir */
6217: tmp = *dxm++ - starts[0];
6218: /* Loop over remaining dimensions */
6219: for (j = 0; j < dim - 1; ++j) {
6220: /* If nonlocal, set index to be negative */
6221: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6222: /* Update local index */
6223: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6224: }
6225: /* Skip component slot if necessary */
6226: if (mat->stencil.noc) dxm++;
6227: /* Local row number */
6228: if (tmp >= 0) jdxm[numNewRows++] = tmp;
6229: }
6230: MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b);
6231: PetscFree(jdxm);
6232: return 0;
6233: }
6235: /*@
6236: MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6237: of a set of rows and columns of a matrix.
6239: Collective
6241: Input Parameters:
6242: + mat - the matrix
6243: . numRows - the number of rows/columns to remove
6244: . rows - the grid coordinates (and component number when dof > 1) for matrix rows
6245: . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6246: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6247: - b - optional vector of right hand side, that will be adjusted by provided solution
6249: Level: intermediate
6251: Notes:
6252: See `MatZeroRowsColumns()` for details on how this routine operates.
6254: The grid coordinates are across the entire grid, not just the local portion
6256: For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6257: obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6258: etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6259: `DM_BOUNDARY_PERIODIC` boundary type.
6261: 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
6262: a single value per point) you can skip filling those indices.
6264: Fortran Note:
6265: In Fortran idxm and idxn should be declared as
6266: $ MatStencil idxm(4,m)
6267: and the values inserted using
6268: .vb
6269: idxm(MatStencil_i,1) = i
6270: idxm(MatStencil_j,1) = j
6271: idxm(MatStencil_k,1) = k
6272: idxm(MatStencil_c,1) = c
6273: etc
6274: .ve
6276: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6277: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6278: @*/
6279: PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6280: {
6281: PetscInt dim = mat->stencil.dim;
6282: PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc);
6283: PetscInt *dims = mat->stencil.dims + 1;
6284: PetscInt *starts = mat->stencil.starts;
6285: PetscInt *dxm = (PetscInt *)rows;
6286: PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6292: PetscMalloc1(numRows, &jdxm);
6293: for (i = 0; i < numRows; ++i) {
6294: /* Skip unused dimensions (they are ordered k, j, i, c) */
6295: for (j = 0; j < 3 - sdim; ++j) dxm++;
6296: /* Local index in X dir */
6297: tmp = *dxm++ - starts[0];
6298: /* Loop over remaining dimensions */
6299: for (j = 0; j < dim - 1; ++j) {
6300: /* If nonlocal, set index to be negative */
6301: if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6302: /* Update local index */
6303: else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6304: }
6305: /* Skip component slot if necessary */
6306: if (mat->stencil.noc) dxm++;
6307: /* Local row number */
6308: if (tmp >= 0) jdxm[numNewRows++] = tmp;
6309: }
6310: MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b);
6311: PetscFree(jdxm);
6312: return 0;
6313: }
6315: /*@C
6316: MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6317: of a set of rows of a matrix; using local numbering of rows.
6319: Collective
6321: Input Parameters:
6322: + mat - the matrix
6323: . numRows - the number of rows to remove
6324: . rows - the local row indices
6325: . diag - value put in all diagonals of eliminated rows
6326: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6327: - b - optional vector of right hand side, that will be adjusted by provided solution
6329: Level: intermediate
6331: Notes:
6332: Before calling `MatZeroRowsLocal()`, the user must first set the
6333: local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6335: See `MatZeroRows()` for details on how this routine operates.
6337: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6338: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6339: @*/
6340: PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6341: {
6347: MatCheckPreallocated(mat, 1);
6349: if (mat->ops->zerorowslocal) {
6350: PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6351: } else {
6352: IS is, newis;
6353: const PetscInt *newRows;
6356: ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6357: ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis);
6358: ISGetIndices(newis, &newRows);
6359: PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6360: ISRestoreIndices(newis, &newRows);
6361: ISDestroy(&newis);
6362: ISDestroy(&is);
6363: }
6364: PetscObjectStateIncrease((PetscObject)mat);
6365: return 0;
6366: }
6368: /*@
6369: MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6370: of a set of rows of a matrix; using local numbering of rows.
6372: Collective
6374: Input Parameters:
6375: + mat - the matrix
6376: . is - index set of rows to remove
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: Level: intermediate
6383: Notes:
6384: Before calling `MatZeroRowsLocalIS()`, the user must first set the
6385: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6387: See `MatZeroRows()` for details on how this routine operates.
6389: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6390: `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6391: @*/
6392: PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6393: {
6394: PetscInt numRows;
6395: const PetscInt *rows;
6402: MatCheckPreallocated(mat, 1);
6404: ISGetLocalSize(is, &numRows);
6405: ISGetIndices(is, &rows);
6406: MatZeroRowsLocal(mat, numRows, rows, diag, x, b);
6407: ISRestoreIndices(is, &rows);
6408: return 0;
6409: }
6411: /*@
6412: MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6413: of a set of rows and columns of a matrix; using local numbering of rows.
6415: Collective
6417: Input Parameters:
6418: + mat - the matrix
6419: . numRows - the number of rows to remove
6420: . rows - the global row indices
6421: . diag - value put in all diagonals of eliminated rows
6422: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6423: - b - optional vector of right hand side, that will be adjusted by provided solution
6425: Level: intermediate
6427: Notes:
6428: Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6429: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6431: See `MatZeroRowsColumns()` for details on how this routine operates.
6433: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6434: `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6435: @*/
6436: PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6437: {
6438: IS is, newis;
6439: const PetscInt *newRows;
6446: MatCheckPreallocated(mat, 1);
6449: ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6450: ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis);
6451: ISGetIndices(newis, &newRows);
6452: PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6453: ISRestoreIndices(newis, &newRows);
6454: ISDestroy(&newis);
6455: ISDestroy(&is);
6456: PetscObjectStateIncrease((PetscObject)mat);
6457: return 0;
6458: }
6460: /*@
6461: MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6462: of a set of rows and columns of a matrix; using local numbering of rows.
6464: Collective on Mat
6466: Input Parameters:
6467: + mat - the matrix
6468: . is - index set of rows to remove
6469: . diag - value put in all diagonals of eliminated rows
6470: . x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6471: - b - optional vector of right hand side, that will be adjusted by provided solution
6473: Level: intermediate
6475: Notes:
6476: Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6477: local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6479: See `MatZeroRowsColumns()` for details on how this routine operates.
6481: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6482: `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6483: @*/
6484: PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6485: {
6486: PetscInt numRows;
6487: const PetscInt *rows;
6494: MatCheckPreallocated(mat, 1);
6496: ISGetLocalSize(is, &numRows);
6497: ISGetIndices(is, &rows);
6498: MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b);
6499: ISRestoreIndices(is, &rows);
6500: return 0;
6501: }
6503: /*@C
6504: MatGetSize - Returns the numbers of rows and columns in a matrix.
6506: Not Collective
6508: Input Parameter:
6509: . mat - the matrix
6511: Level: beginner
6513: Output Parameters:
6514: + m - the number of global rows
6515: - n - the number of global columns
6517: Note:
6518: Both output parameters can be `NULL` on input.
6520: .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6521: @*/
6522: PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6523: {
6525: if (m) *m = mat->rmap->N;
6526: if (n) *n = mat->cmap->N;
6527: return 0;
6528: }
6530: /*@C
6531: MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6532: of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6534: Not Collective
6536: Input Parameter:
6537: . mat - the matrix
6539: Output Parameters:
6540: + m - the number of local rows, use `NULL` to not obtain this value
6541: - n - the number of local columns, use `NULL` to not obtain this value
6543: Level: beginner
6545: .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6546: @*/
6547: PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6548: {
6552: if (m) *m = mat->rmap->n;
6553: if (n) *n = mat->cmap->n;
6554: return 0;
6555: }
6557: /*@C
6558: MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6559: this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6561: Not Collective, unless matrix has not been allocated, then collective
6563: Input Parameter:
6564: . mat - the matrix
6566: Output Parameters:
6567: + m - the global index of the first local column, use `NULL` to not obtain this value
6568: - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6570: Level: developer
6572: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6573: @*/
6574: PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6575: {
6580: MatCheckPreallocated(mat, 1);
6581: if (m) *m = mat->cmap->rstart;
6582: if (n) *n = mat->cmap->rend;
6583: return 0;
6584: }
6586: /*@C
6587: MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6588: 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
6589: vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6591: Not Collective
6593: Input Parameter:
6594: . mat - the matrix
6596: Output Parameters:
6597: + m - the global index of the first local row, use `NULL` to not obtain this value
6598: - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6600: Level: beginner
6602: Note:
6603: This function requires that the matrix be preallocated. If you have not preallocated, consider using
6604: `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6605: and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6607: .seealso: `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6608: `PetscLayout`
6609: @*/
6610: PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6611: {
6616: MatCheckPreallocated(mat, 1);
6617: if (m) *m = mat->rmap->rstart;
6618: if (n) *n = mat->rmap->rend;
6619: return 0;
6620: }
6622: /*@C
6623: MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6624: 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
6625: vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6627: Not Collective, unless matrix has not been allocated, then collective
6629: Input Parameters:
6630: . mat - the matrix
6632: Output Parameters:
6633: . ranges - start of each processors portion plus one more than the total length at the end
6635: Level: beginner
6637: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6638: @*/
6639: PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6640: {
6643: MatCheckPreallocated(mat, 1);
6644: PetscLayoutGetRanges(mat->rmap, ranges);
6645: return 0;
6646: }
6648: /*@C
6649: MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6650: each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6652: Not Collective, unless matrix has not been allocated, then collective on Mat
6654: Input Parameters:
6655: . mat - the matrix
6657: Output Parameters:
6658: . ranges - start of each processors portion plus one more then the total length at the end
6660: Level: beginner
6662: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6663: @*/
6664: PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6665: {
6668: MatCheckPreallocated(mat, 1);
6669: PetscLayoutGetRanges(mat->cmap, ranges);
6670: return 0;
6671: }
6673: /*@C
6674: MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6675: corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6676: is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6678: Not Collective
6680: Input Parameter:
6681: . A - matrix
6683: Output Parameters:
6684: + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6685: - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6687: Level: intermediate
6689: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6690: @*/
6691: PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6692: {
6693: PetscErrorCode (*f)(Mat, IS *, IS *);
6695: MatCheckPreallocated(A, 1);
6696: PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f);
6697: if (f) {
6698: (*f)(A, rows, cols);
6699: } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6700: if (rows) ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows);
6701: if (cols) ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols);
6702: }
6703: return 0;
6704: }
6706: /*@C
6707: MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6708: Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6709: to complete the factorization.
6711: Collective on fact
6713: Input Parameters:
6714: + fact - the factorized matrix obtained with `MatGetFactor()`
6715: . mat - the matrix
6716: . row - row permutation
6717: . column - column permutation
6718: - info - structure containing
6719: .vb
6720: levels - number of levels of fill.
6721: expected fill - as ratio of original fill.
6722: 1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6723: missing diagonal entries)
6724: .ve
6726: Output Parameters:
6727: . fact - new matrix that has been symbolically factored
6729: Level: developer
6731: Notes:
6732: See [Matrix Factorization](sec_matfactor) for additional information.
6734: Most users should employ the `KSP` interface for linear solvers
6735: instead of working directly with matrix algebra routines such as this.
6736: See, e.g., `KSPCreate()`.
6738: Uses the definition of level of fill as in Y. Saad, 2003
6740: Developer Note:
6741: The Fortran interface is not autogenerated as the
6742: interface definition cannot be generated correctly [due to `MatFactorInfo`]
6744: References:
6745: . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6747: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6748: `MatGetOrdering()`, `MatFactorInfo`
6749: @*/
6750: PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6751: {
6760: if (!fact->ops->ilufactorsymbolic) {
6761: MatSolverType stype;
6762: MatFactorGetSolverType(fact, &stype);
6763: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6764: }
6767: MatCheckPreallocated(mat, 2);
6769: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0);
6770: (fact->ops->ilufactorsymbolic)(fact, mat, row, col, info);
6771: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0);
6772: return 0;
6773: }
6775: /*@C
6776: MatICCFactorSymbolic - Performs symbolic incomplete
6777: Cholesky factorization for a symmetric matrix. Use
6778: `MatCholeskyFactorNumeric()` to complete the factorization.
6780: Collective on fact
6782: Input Parameters:
6783: + fact - the factorized matrix obtained with `MatGetFactor()`
6784: . mat - the matrix to be factored
6785: . perm - row and column permutation
6786: - info - structure containing
6787: .vb
6788: levels - number of levels of fill.
6789: expected fill - as ratio of original fill.
6790: .ve
6792: Output Parameter:
6793: . fact - the factored matrix
6795: Level: developer
6797: Notes:
6798: Most users should employ the `KSP` interface for linear solvers
6799: instead of working directly with matrix algebra routines such as this.
6800: See, e.g., `KSPCreate()`.
6802: This uses the definition of level of fill as in Y. Saad, 2003
6804: Developer Note:
6805: The Fortran interface is not autogenerated as the
6806: interface definition cannot be generated correctly [due to `MatFactorInfo`]
6808: References:
6809: . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6811: .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6812: @*/
6813: PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6814: {
6823: if (!(fact)->ops->iccfactorsymbolic) {
6824: MatSolverType stype;
6825: MatFactorGetSolverType(fact, &stype);
6826: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6827: }
6829: MatCheckPreallocated(mat, 2);
6831: if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6832: (fact->ops->iccfactorsymbolic)(fact, mat, perm, info);
6833: if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6834: return 0;
6835: }
6837: /*@C
6838: MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6839: points to an array of valid matrices, they may be reused to store the new
6840: submatrices.
6842: Collective
6844: Input Parameters:
6845: + mat - the matrix
6846: . n - the number of submatrixes to be extracted (on this processor, may be zero)
6847: . irow, icol - index sets of rows and columns to extract
6848: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6850: Output Parameter:
6851: . submat - the array of submatrices
6853: Level: advanced
6855: Notes:
6856: `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6857: (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6858: to extract a parallel submatrix.
6860: Some matrix types place restrictions on the row and column
6861: indices, such as that they be sorted or that they be equal to each other.
6863: The index sets may not have duplicate entries.
6865: When extracting submatrices from a parallel matrix, each processor can
6866: form a different submatrix by setting the rows and columns of its
6867: individual index sets according to the local submatrix desired.
6869: When finished using the submatrices, the user should destroy
6870: them with `MatDestroySubMatrices()`.
6872: `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6873: original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6875: This routine creates the matrices in submat; you should NOT create them before
6876: calling it. It also allocates the array of matrix pointers submat.
6878: For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6879: request one row/column in a block, they must request all rows/columns that are in
6880: that block. For example, if the block size is 2 you cannot request just row 0 and
6881: column 0.
6883: Fortran Note:
6884: The Fortran interface is slightly different from that given below; it
6885: requires one to pass in as submat a `Mat` (integer) array of size at least n+1.
6887: .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6888: @*/
6889: PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6890: {
6891: PetscInt i;
6892: PetscBool eq;
6896: if (n) {
6901: }
6903: if (n && scall == MAT_REUSE_MATRIX) {
6906: }
6909: MatCheckPreallocated(mat, 1);
6910: PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6911: PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6912: PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6913: for (i = 0; i < n; i++) {
6914: (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6915: ISEqualUnsorted(irow[i], icol[i], &eq);
6916: if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6917: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
6918: if (mat->boundtocpu && mat->bindingpropagates) {
6919: MatBindToCPU((*submat)[i], PETSC_TRUE);
6920: MatSetBindingPropagates((*submat)[i], PETSC_TRUE);
6921: }
6922: #endif
6923: }
6924: return 0;
6925: }
6927: /*@C
6928: MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
6930: Collective
6932: Input Parameters:
6933: + mat - the matrix
6934: . n - the number of submatrixes to be extracted
6935: . irow, icol - index sets of rows and columns to extract
6936: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6938: Output Parameter:
6939: . submat - the array of submatrices
6941: Level: advanced
6943: Note:
6944: This is used by `PCGASM`
6946: .seealso: `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6947: @*/
6948: PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6949: {
6950: PetscInt i;
6951: PetscBool eq;
6955: if (n) {
6960: }
6962: if (n && scall == MAT_REUSE_MATRIX) {
6965: }
6968: MatCheckPreallocated(mat, 1);
6970: PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6971: PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6972: PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6973: for (i = 0; i < n; i++) {
6974: ISEqualUnsorted(irow[i], icol[i], &eq);
6975: if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6976: }
6977: return 0;
6978: }
6980: /*@C
6981: MatDestroyMatrices - Destroys an array of matrices.
6983: Collective
6985: Input Parameters:
6986: + n - the number of local matrices
6987: - mat - the matrices (note that this is a pointer to the array of matrices)
6989: Level: advanced
6991: Note:
6992: Frees not only the matrices, but also the array that contains the matrices
6994: Fortran Note:
6995: Will not free the array.
6997: .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6998: @*/
6999: PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7000: {
7001: PetscInt i;
7003: if (!*mat) return 0;
7007: for (i = 0; i < n; i++) MatDestroy(&(*mat)[i]);
7009: /* memory is allocated even if n = 0 */
7010: PetscFree(*mat);
7011: return 0;
7012: }
7014: /*@C
7015: MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7017: Collective
7019: Input Parameters:
7020: + n - the number of local matrices
7021: - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7022: sequence of MatCreateSubMatrices())
7024: Level: advanced
7026: Note:
7027: Frees not only the matrices, but also the array that contains the matrices
7029: Fortran Note:
7030: Will not free the array.
7032: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7033: @*/
7034: PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7035: {
7036: Mat mat0;
7038: if (!*mat) return 0;
7039: /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7043: mat0 = (*mat)[0];
7044: if (mat0 && mat0->ops->destroysubmatrices) {
7045: (mat0->ops->destroysubmatrices)(n, mat);
7046: } else {
7047: MatDestroyMatrices(n, mat);
7048: }
7049: return 0;
7050: }
7052: /*@C
7053: MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7055: Collective
7057: Input Parameters:
7058: . mat - the matrix
7060: Output Parameter:
7061: . matstruct - the sequential matrix with the nonzero structure of mat
7063: Level: developer
7065: .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7066: @*/
7067: PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7068: {
7074: MatCheckPreallocated(mat, 1);
7076: PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7077: PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7078: PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7079: return 0;
7080: }
7082: /*@C
7083: MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7085: Collective
7087: Input Parameters:
7088: . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7089: sequence of `MatGetSequentialNonzeroStructure()`)
7091: Level: advanced
7093: Note:
7094: Frees not only the matrices, but also the array that contains the matrices
7096: .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7097: @*/
7098: PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7099: {
7101: MatDestroy(mat);
7102: return 0;
7103: }
7105: /*@
7106: MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7107: replaces the index sets by larger ones that represent submatrices with
7108: additional overlap.
7110: Collective
7112: Input Parameters:
7113: + mat - the matrix
7114: . n - the number of index sets
7115: . is - the array of index sets (these index sets will changed during the call)
7116: - ov - the additional overlap requested
7118: Options Database Key:
7119: . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7121: Level: developer
7123: Note:
7124: The computed overlap preserves the matrix block sizes when the blocks are square.
7125: That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7126: that block are included in the overlap regardless of whether each specific column would increase the overlap.
7128: .seealso: `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7129: @*/
7130: PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7131: {
7132: PetscInt i, bs, cbs;
7138: if (n) {
7141: }
7144: MatCheckPreallocated(mat, 1);
7146: if (!ov || !n) return 0;
7147: PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7148: PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7149: PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7150: MatGetBlockSizes(mat, &bs, &cbs);
7151: if (bs == cbs) {
7152: for (i = 0; i < n; i++) ISSetBlockSize(is[i], bs);
7153: }
7154: return 0;
7155: }
7157: PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7159: /*@
7160: MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7161: a sub communicator, replaces the index sets by larger ones that represent submatrices with
7162: additional overlap.
7164: Collective
7166: Input Parameters:
7167: + mat - the matrix
7168: . n - the number of index sets
7169: . is - the array of index sets (these index sets will changed during the call)
7170: - ov - the additional overlap requested
7172: ` Options Database Key:
7173: . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7175: Level: developer
7177: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7178: @*/
7179: PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7180: {
7181: PetscInt i;
7186: if (n) {
7189: }
7192: MatCheckPreallocated(mat, 1);
7193: if (!ov) return 0;
7194: PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7195: for (i = 0; i < n; i++) MatIncreaseOverlapSplit_Single(mat, &is[i], ov);
7196: PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7197: return 0;
7198: }
7200: /*@
7201: MatGetBlockSize - Returns the matrix block size.
7203: Not Collective
7205: Input Parameter:
7206: . mat - the matrix
7208: Output Parameter:
7209: . bs - block size
7211: Level: intermediate
7213: Notes:
7214: Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7216: If the block size has not been set yet this routine returns 1.
7218: .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7219: @*/
7220: PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7221: {
7224: *bs = PetscAbs(mat->rmap->bs);
7225: return 0;
7226: }
7228: /*@
7229: MatGetBlockSizes - Returns the matrix block row and column sizes.
7231: Not Collective
7233: Input Parameter:
7234: . mat - the matrix
7236: Output Parameters:
7237: + rbs - row block size
7238: - cbs - column block size
7240: Level: intermediate
7242: Notes:
7243: Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7244: If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7246: If a block size has not been set yet this routine returns 1.
7248: .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7249: @*/
7250: PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7251: {
7255: if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7256: if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7257: return 0;
7258: }
7260: /*@
7261: MatSetBlockSize - Sets the matrix block size.
7263: Logically Collective
7265: Input Parameters:
7266: + mat - the matrix
7267: - bs - block size
7269: Level: intermediate
7271: Notes:
7272: Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7273: This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7275: For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7276: is compatible with the matrix local sizes.
7278: .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7279: @*/
7280: PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7281: {
7284: MatSetBlockSizes(mat, bs, bs);
7285: return 0;
7286: }
7288: typedef struct {
7289: PetscInt n;
7290: IS *is;
7291: Mat *mat;
7292: PetscObjectState nonzerostate;
7293: Mat C;
7294: } EnvelopeData;
7296: static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7297: {
7298: for (PetscInt i = 0; i < edata->n; i++) ISDestroy(&edata->is[i]);
7299: PetscFree(edata->is);
7300: PetscFree(edata);
7301: return 0;
7302: }
7304: /*
7305: MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7306: the sizes of these blocks in the matrix. An individual block may lie over several processes.
7308: Collective
7310: Input Parameter:
7311: . mat - the matrix
7313: Notes:
7314: There can be zeros within the blocks
7316: The blocks can overlap between processes, including laying on more than two processes
7318: .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7319: */
7320: static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7321: {
7322: PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7323: PetscInt *diag, *odiag, sc;
7324: VecScatter scatter;
7325: PetscScalar *seqv;
7326: const PetscScalar *parv;
7327: const PetscInt *ia, *ja;
7328: PetscBool set, flag, done;
7329: Mat AA = mat, A;
7330: MPI_Comm comm;
7331: PetscMPIInt rank, size, tag;
7332: MPI_Status status;
7333: PetscContainer container;
7334: EnvelopeData *edata;
7335: Vec seq, par;
7336: IS isglobal;
7339: MatIsSymmetricKnown(mat, &set, &flag);
7340: if (!set || !flag) {
7341: /* TOO: only needs nonzero structure of transpose */
7342: MatTranspose(mat, MAT_INITIAL_MATRIX, &AA);
7343: MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN);
7344: }
7345: MatAIJGetLocalMat(AA, &A);
7346: MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7349: MatGetLocalSize(mat, &n, NULL);
7350: PetscObjectGetNewTag((PetscObject)mat, &tag);
7351: PetscObjectGetComm((PetscObject)mat, &comm);
7352: MPI_Comm_size(comm, &size);
7353: MPI_Comm_rank(comm, &rank);
7355: PetscMalloc2(n, &sizes, n, &starts);
7357: if (rank > 0) {
7358: MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status);
7359: MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status);
7360: }
7361: MatGetOwnershipRange(mat, &rstart, NULL);
7362: for (i = 0; i < n; i++) {
7363: env = PetscMax(env, ja[ia[i + 1] - 1]);
7364: II = rstart + i;
7365: if (env == II) {
7366: starts[lblocks] = tbs;
7367: sizes[lblocks++] = 1 + II - tbs;
7368: tbs = 1 + II;
7369: }
7370: }
7371: if (rank < size - 1) {
7372: MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm);
7373: MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm);
7374: }
7376: MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7377: if (!set || !flag) MatDestroy(&AA);
7378: MatDestroy(&A);
7380: PetscNew(&edata);
7381: MatGetNonzeroState(mat, &edata->nonzerostate);
7382: edata->n = lblocks;
7383: /* create IS needed for extracting blocks from the original matrix */
7384: PetscMalloc1(lblocks, &edata->is);
7385: for (PetscInt i = 0; i < lblocks; i++) ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]);
7387: /* Create the resulting inverse matrix structure with preallocation information */
7388: MatCreate(PetscObjectComm((PetscObject)mat), &edata->C);
7389: MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
7390: MatSetBlockSizesFromMats(edata->C, mat, mat);
7391: MatSetType(edata->C, MATAIJ);
7393: /* Communicate the start and end of each row, from each block to the correct rank */
7394: /* TODO: Use PetscSF instead of VecScatter */
7395: for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7396: VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq);
7397: VecGetArrayWrite(seq, &seqv);
7398: for (PetscInt i = 0; i < lblocks; i++) {
7399: for (PetscInt j = 0; j < sizes[i]; j++) {
7400: seqv[cnt] = starts[i];
7401: seqv[cnt + 1] = starts[i] + sizes[i];
7402: cnt += 2;
7403: }
7404: }
7405: VecRestoreArrayWrite(seq, &seqv);
7406: MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
7407: sc -= cnt;
7408: VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par);
7409: ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal);
7410: VecScatterCreate(seq, NULL, par, isglobal, &scatter);
7411: ISDestroy(&isglobal);
7412: VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7413: VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7414: VecScatterDestroy(&scatter);
7415: VecDestroy(&seq);
7416: MatGetOwnershipRangeColumn(mat, &cstart, &cend);
7417: PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag);
7418: VecGetArrayRead(par, &parv);
7419: cnt = 0;
7420: MatGetSize(mat, NULL, &n);
7421: for (PetscInt i = 0; i < mat->rmap->n; i++) {
7422: PetscInt start, end, d = 0, od = 0;
7424: start = (PetscInt)PetscRealPart(parv[cnt]);
7425: end = (PetscInt)PetscRealPart(parv[cnt + 1]);
7426: cnt += 2;
7428: if (start < cstart) {
7429: od += cstart - start + n - cend;
7430: d += cend - cstart;
7431: } else if (start < cend) {
7432: od += n - cend;
7433: d += cend - start;
7434: } else od += n - start;
7435: if (end <= cstart) {
7436: od -= cstart - end + n - cend;
7437: d -= cend - cstart;
7438: } else if (end < cend) {
7439: od -= n - cend;
7440: d -= cend - end;
7441: } else od -= n - end;
7443: odiag[i] = od;
7444: diag[i] = d;
7445: }
7446: VecRestoreArrayRead(par, &parv);
7447: VecDestroy(&par);
7448: MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL);
7449: PetscFree2(diag, odiag);
7450: PetscFree2(sizes, starts);
7452: PetscContainerCreate(PETSC_COMM_SELF, &container);
7453: PetscContainerSetPointer(container, edata);
7454: PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy);
7455: PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container);
7456: PetscObjectDereference((PetscObject)container);
7457: return 0;
7458: }
7460: /*@
7461: MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7463: Collective
7465: Input Parameters:
7466: . A - the matrix
7468: Output Parameters:
7469: . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set.
7471: Level: advanced
7473: Note:
7474: For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7476: .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7477: @*/
7478: PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7479: {
7480: PetscContainer container;
7481: EnvelopeData *edata;
7482: PetscObjectState nonzerostate;
7484: PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7485: if (!container) {
7486: MatComputeVariableBlockEnvelope(A);
7487: PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7488: }
7489: PetscContainerGetPointer(container, (void **)&edata);
7490: MatGetNonzeroState(A, &nonzerostate);
7494: MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat);
7495: *C = edata->C;
7497: for (PetscInt i = 0; i < edata->n; i++) {
7498: Mat D;
7499: PetscScalar *dvalues;
7501: MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D);
7502: MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE);
7503: MatSeqDenseInvert(D);
7504: MatDenseGetArray(D, &dvalues);
7505: MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES);
7506: MatDestroy(&D);
7507: }
7508: MatDestroySubMatrices(edata->n, &edata->mat);
7509: MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY);
7510: MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY);
7511: return 0;
7512: }
7514: /*@
7515: MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7517: Logically Collective
7519: Input Parameters:
7520: + mat - the matrix
7521: . nblocks - the number of blocks on this process, each block can only exist on a single process
7522: - bsizes - the block sizes
7524: Level: intermediate
7526: Notes:
7527: Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7529: 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.
7531: .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7532: `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7533: @*/
7534: PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7535: {
7536: PetscInt i, ncnt = 0, nlocal;
7540: MatGetLocalSize(mat, &nlocal, NULL);
7541: for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7543: PetscFree(mat->bsizes);
7544: mat->nblocks = nblocks;
7545: PetscMalloc1(nblocks, &mat->bsizes);
7546: PetscArraycpy(mat->bsizes, bsizes, nblocks);
7547: return 0;
7548: }
7550: /*@C
7551: MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7553: Logically Collective; No Fortran Support
7555: Input Parameter:
7556: . mat - the matrix
7558: Output Parameters:
7559: + nblocks - the number of blocks on this process
7560: - bsizes - the block sizes
7562: Level: intermediate
7564: .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7565: @*/
7566: PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7567: {
7569: *nblocks = mat->nblocks;
7570: *bsizes = mat->bsizes;
7571: return 0;
7572: }
7574: /*@
7575: MatSetBlockSizes - Sets the matrix block row and column sizes.
7577: Logically Collective
7579: Input Parameters:
7580: + mat - the matrix
7581: . rbs - row block size
7582: - cbs - column block size
7584: Level: intermediate
7586: Notes:
7587: Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7588: If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7589: This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7591: For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7592: are compatible with the matrix local sizes.
7594: The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7596: .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7597: @*/
7598: PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7599: {
7603: PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7604: if (mat->rmap->refcnt) {
7605: ISLocalToGlobalMapping l2g = NULL;
7606: PetscLayout nmap = NULL;
7608: PetscLayoutDuplicate(mat->rmap, &nmap);
7609: if (mat->rmap->mapping) ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g);
7610: PetscLayoutDestroy(&mat->rmap);
7611: mat->rmap = nmap;
7612: mat->rmap->mapping = l2g;
7613: }
7614: if (mat->cmap->refcnt) {
7615: ISLocalToGlobalMapping l2g = NULL;
7616: PetscLayout nmap = NULL;
7618: PetscLayoutDuplicate(mat->cmap, &nmap);
7619: if (mat->cmap->mapping) ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g);
7620: PetscLayoutDestroy(&mat->cmap);
7621: mat->cmap = nmap;
7622: mat->cmap->mapping = l2g;
7623: }
7624: PetscLayoutSetBlockSize(mat->rmap, rbs);
7625: PetscLayoutSetBlockSize(mat->cmap, cbs);
7626: return 0;
7627: }
7629: /*@
7630: MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7632: Logically Collective
7634: Input Parameters:
7635: + mat - the matrix
7636: . fromRow - matrix from which to copy row block size
7637: - fromCol - matrix from which to copy column block size (can be same as fromRow)
7639: Level: developer
7641: .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7642: @*/
7643: PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7644: {
7648: if (fromRow->rmap->bs > 0) PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs);
7649: if (fromCol->cmap->bs > 0) PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs);
7650: return 0;
7651: }
7653: /*@
7654: MatResidual - Default routine to calculate the residual r = b - Ax
7656: Collective
7658: Input Parameters:
7659: + mat - the matrix
7660: . b - the right-hand-side
7661: - x - the approximate solution
7663: Output Parameter:
7664: . r - location to store the residual
7666: Level: developer
7668: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7669: @*/
7670: PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7671: {
7677: MatCheckPreallocated(mat, 1);
7678: PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0);
7679: if (!mat->ops->residual) {
7680: MatMult(mat, x, r);
7681: VecAYPX(r, -1.0, b);
7682: } else {
7683: PetscUseTypeMethod(mat, residual, b, x, r);
7684: }
7685: PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0);
7686: return 0;
7687: }
7689: /*@C
7690: MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7692: Collective
7694: Input Parameters:
7695: + mat - the matrix
7696: . shift - 0 or 1 indicating we want the indices starting at 0 or 1
7697: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7698: - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the
7699: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7700: always used.
7702: Output Parameters:
7703: + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7704: . 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
7705: . ja - the column indices, use `NULL` if not needed
7706: - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7707: are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7709: Level: developer
7711: Notes:
7712: You CANNOT change any of the ia[] or ja[] values.
7714: Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7716: Fortran Notes:
7717: In Fortran use
7718: .vb
7719: PetscInt ia(1), ja(1)
7720: PetscOffset iia, jja
7721: call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7722: ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7723: .ve
7724: or
7725: .vb
7726: PetscInt, pointer :: ia(:),ja(:)
7727: call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7728: ! Access the ith and jth entries via ia(i) and ja(j)
7729: .ve
7731: .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7732: @*/
7733: PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7734: {
7741: MatCheckPreallocated(mat, 1);
7742: if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7743: else {
7744: if (done) *done = PETSC_TRUE;
7745: PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0);
7746: PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7747: PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0);
7748: }
7749: return 0;
7750: }
7752: /*@C
7753: MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7755: Collective
7757: Input Parameters:
7758: + mat - the matrix
7759: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7760: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7761: symmetrized
7762: . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7763: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7764: always used.
7765: . n - number of columns in the (possibly compressed) matrix
7766: . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7767: - ja - the row indices
7769: Output Parameters:
7770: . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7772: Level: developer
7774: .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7775: @*/
7776: PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7777: {
7784: MatCheckPreallocated(mat, 1);
7785: if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7786: else {
7787: *done = PETSC_TRUE;
7788: PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7789: }
7790: return 0;
7791: }
7793: /*@C
7794: MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7796: Collective
7798: Input Parameters:
7799: + mat - the matrix
7800: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7801: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7802: . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7803: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7804: always used.
7805: . n - size of (possibly compressed) matrix
7806: . ia - the row pointers
7807: - ja - the column indices
7809: Output Parameters:
7810: . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7812: Level: developer
7814: Note:
7815: This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
7816: us of the array after it has been restored. If you pass `NULL`, it will
7817: not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7819: .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7820: @*/
7821: PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7822: {
7828: MatCheckPreallocated(mat, 1);
7830: if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7831: else {
7832: if (done) *done = PETSC_TRUE;
7833: PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7834: if (n) *n = 0;
7835: if (ia) *ia = NULL;
7836: if (ja) *ja = NULL;
7837: }
7838: return 0;
7839: }
7841: /*@C
7842: MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
7844: Collective on Mat
7846: Input Parameters:
7847: + mat - the matrix
7848: . shift - 1 or zero indicating we want the indices starting at 0 or 1
7849: . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7850: - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7851: inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7852: always used.
7854: Output Parameters:
7855: + n - size of (possibly compressed) matrix
7856: . ia - the column pointers
7857: . ja - the row indices
7858: - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7860: Level: developer
7862: .seealso: `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7863: @*/
7864: PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7865: {
7871: MatCheckPreallocated(mat, 1);
7873: if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7874: else {
7875: *done = PETSC_TRUE;
7876: PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7877: if (n) *n = 0;
7878: if (ia) *ia = NULL;
7879: if (ja) *ja = NULL;
7880: }
7881: return 0;
7882: }
7884: /*@C
7885: MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
7887: Collective
7889: Input Parameters:
7890: + mat - the matrix
7891: . ncolors - max color value
7892: . n - number of entries in colorarray
7893: - colorarray - array indicating color for each column
7895: Output Parameters:
7896: . iscoloring - coloring generated using colorarray information
7898: Level: developer
7900: .seealso: `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
7901: @*/
7902: PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
7903: {
7908: MatCheckPreallocated(mat, 1);
7910: if (!mat->ops->coloringpatch) {
7911: ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring);
7912: } else {
7913: PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7914: }
7915: return 0;
7916: }
7918: /*@
7919: MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
7921: Logically Collective
7923: Input Parameter:
7924: . mat - the factored matrix to be reset
7926: Level: developer
7928: Notes:
7929: This routine should be used only with factored matrices formed by in-place
7930: factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
7931: format). This option can save memory, for example, when solving nonlinear
7932: systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7933: ILU(0) preconditioner.
7935: Note that one can specify in-place ILU(0) factorization by calling
7936: .vb
7937: PCType(pc,PCILU);
7938: PCFactorSeUseInPlace(pc);
7939: .ve
7940: or by using the options -pc_type ilu -pc_factor_in_place
7942: In-place factorization ILU(0) can also be used as a local
7943: solver for the blocks within the block Jacobi or additive Schwarz
7944: methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc
7945: for details on setting local solver options.
7947: Most users should employ the `KSP` interface for linear solvers
7948: instead of working directly with matrix algebra routines such as this.
7949: See, e.g., `KSPCreate()`.
7951: .seealso: `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7952: @*/
7953: PetscErrorCode MatSetUnfactored(Mat mat)
7954: {
7957: MatCheckPreallocated(mat, 1);
7958: mat->factortype = MAT_FACTOR_NONE;
7959: if (!mat->ops->setunfactored) return 0;
7960: PetscUseTypeMethod(mat, setunfactored);
7961: return 0;
7962: }
7964: /*MC
7965: MatDenseGetArrayF90 - Accesses a matrix array from Fortran
7967: Synopsis:
7968: MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7970: Not collective
7972: Input Parameter:
7973: . x - matrix
7975: Output Parameters:
7976: + xx_v - the Fortran pointer to the array
7977: - ierr - error code
7979: Example of Usage:
7980: .vb
7981: PetscScalar, pointer xx_v(:,:)
7982: ....
7983: call MatDenseGetArrayF90(x,xx_v,ierr)
7984: a = xx_v(3)
7985: call MatDenseRestoreArrayF90(x,xx_v,ierr)
7986: .ve
7988: Level: advanced
7990: .seealso: `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
7991: M*/
7993: /*MC
7994: MatDenseRestoreArrayF90 - Restores a matrix array that has been
7995: accessed with `MatDenseGetArrayF90()`.
7997: Synopsis:
7998: MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8000: Not collective
8002: Input Parameters:
8003: + x - matrix
8004: - xx_v - the Fortran90 pointer to the array
8006: Output Parameter:
8007: . ierr - error code
8009: Example of Usage:
8010: .vb
8011: PetscScalar, pointer xx_v(:,:)
8012: ....
8013: call MatDenseGetArrayF90(x,xx_v,ierr)
8014: a = xx_v(3)
8015: call MatDenseRestoreArrayF90(x,xx_v,ierr)
8016: .ve
8018: Level: advanced
8020: .seealso: `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8021: M*/
8023: /*MC
8024: MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8026: Synopsis:
8027: MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8029: Not collective
8031: Input Parameter:
8032: . x - matrix
8034: Output Parameters:
8035: + xx_v - the Fortran pointer to the array
8036: - ierr - error code
8038: Example of Usage:
8039: .vb
8040: PetscScalar, pointer xx_v(:)
8041: ....
8042: call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8043: a = xx_v(3)
8044: call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8045: .ve
8047: Level: advanced
8049: .seealso: `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8050: M*/
8052: /*MC
8053: MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8054: accessed with `MatSeqAIJGetArrayF90()`.
8056: Synopsis:
8057: MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8059: Not collective
8061: Input Parameters:
8062: + x - matrix
8063: - xx_v - the Fortran90 pointer to the array
8065: Output Parameter:
8066: . ierr - error code
8068: Example of Usage:
8069: .vb
8070: PetscScalar, pointer xx_v(:)
8071: ....
8072: call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8073: a = xx_v(3)
8074: call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8075: .ve
8077: Level: advanced
8079: .seealso: `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8080: M*/
8082: /*@
8083: MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8084: as the original matrix.
8086: Collective
8088: Input Parameters:
8089: + mat - the original matrix
8090: . isrow - parallel IS containing the rows this processor should obtain
8091: . 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.
8092: - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8094: Output Parameter:
8095: . newmat - the new submatrix, of the same type as the old
8097: Level: advanced
8099: Notes:
8100: The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8102: Some matrix types place restrictions on the row and column indices, such
8103: as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block;
8104: for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8106: The index sets may not have duplicate entries.
8108: The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8109: the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8110: to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8111: will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when
8112: you are finished using it.
8114: The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8115: the input matrix.
8117: If iscol is `NULL` then all columns are obtained (not supported in Fortran).
8119: Example usage:
8120: Consider the following 8x8 matrix with 34 non-zero values, that is
8121: assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8122: proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8123: as follows:
8125: .vb
8126: 1 2 0 | 0 3 0 | 0 4
8127: Proc0 0 5 6 | 7 0 0 | 8 0
8128: 9 0 10 | 11 0 0 | 12 0
8129: -------------------------------------
8130: 13 0 14 | 15 16 17 | 0 0
8131: Proc1 0 18 0 | 19 20 21 | 0 0
8132: 0 0 0 | 22 23 0 | 24 0
8133: -------------------------------------
8134: Proc2 25 26 27 | 0 0 28 | 29 0
8135: 30 0 0 | 31 32 33 | 0 34
8136: .ve
8138: Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is
8140: .vb
8141: 2 0 | 0 3 0 | 0
8142: Proc0 5 6 | 7 0 0 | 8
8143: -------------------------------
8144: Proc1 18 0 | 19 20 21 | 0
8145: -------------------------------
8146: Proc2 26 27 | 0 0 28 | 29
8147: 0 0 | 31 32 33 | 0
8148: .ve
8150: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8151: @*/
8152: PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8153: {
8154: PetscMPIInt size;
8155: Mat *local;
8156: IS iscoltmp;
8157: PetscBool flg;
8168: MatCheckPreallocated(mat, 1);
8169: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8171: if (!iscol || isrow == iscol) {
8172: PetscBool stride;
8173: PetscMPIInt grabentirematrix = 0, grab;
8174: PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride);
8175: if (stride) {
8176: PetscInt first, step, n, rstart, rend;
8177: ISStrideGetInfo(isrow, &first, &step);
8178: if (step == 1) {
8179: MatGetOwnershipRange(mat, &rstart, &rend);
8180: if (rstart == first) {
8181: ISGetLocalSize(isrow, &n);
8182: if (n == rend - rstart) grabentirematrix = 1;
8183: }
8184: }
8185: }
8186: MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat));
8187: if (grab) {
8188: PetscInfo(mat, "Getting entire matrix as submatrix\n");
8189: if (cll == MAT_INITIAL_MATRIX) {
8190: *newmat = mat;
8191: PetscObjectReference((PetscObject)mat);
8192: }
8193: return 0;
8194: }
8195: }
8197: if (!iscol) {
8198: ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp);
8199: } else {
8200: iscoltmp = iscol;
8201: }
8203: /* if original matrix is on just one processor then use submatrix generated */
8204: if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8205: MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat);
8206: goto setproperties;
8207: } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8208: MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local);
8209: *newmat = *local;
8210: PetscFree(local);
8211: goto setproperties;
8212: } else if (!mat->ops->createsubmatrix) {
8213: /* Create a new matrix type that implements the operation using the full matrix */
8214: PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8215: switch (cll) {
8216: case MAT_INITIAL_MATRIX:
8217: MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat);
8218: break;
8219: case MAT_REUSE_MATRIX:
8220: MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp);
8221: break;
8222: default:
8223: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8224: }
8225: PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8226: goto setproperties;
8227: }
8229: PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8230: PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8231: PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8233: setproperties:
8234: ISEqualUnsorted(isrow, iscoltmp, &flg);
8235: if (flg) MatPropagateSymmetryOptions(mat, *newmat);
8236: if (!iscol) ISDestroy(&iscoltmp);
8237: if (*newmat && cll == MAT_INITIAL_MATRIX) PetscObjectStateIncrease((PetscObject)*newmat);
8238: return 0;
8239: }
8241: /*@
8242: MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8244: Not Collective
8246: Input Parameters:
8247: + A - the matrix we wish to propagate options from
8248: - B - the matrix we wish to propagate options to
8250: Level: beginner
8252: Note:
8253: Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8255: .seealso: `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8256: @*/
8257: PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8258: {
8261: B->symmetry_eternal = A->symmetry_eternal;
8262: B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8263: B->symmetric = A->symmetric;
8264: B->structurally_symmetric = A->structurally_symmetric;
8265: B->spd = A->spd;
8266: B->hermitian = A->hermitian;
8267: return 0;
8268: }
8270: /*@
8271: MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8272: used during the assembly process to store values that belong to
8273: other processors.
8275: Not Collective
8277: Input Parameters:
8278: + mat - the matrix
8279: . size - the initial size of the stash.
8280: - bsize - the initial size of the block-stash(if used).
8282: Options Database Keys:
8283: + -matstash_initial_size <size> or <size0,size1,...sizep-1>
8284: - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1>
8286: Level: intermediate
8288: Notes:
8289: The block-stash is used for values set with `MatSetValuesBlocked()` while
8290: the stash is used for values set with `MatSetValues()`
8292: Run with the option -info and look for output of the form
8293: MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8294: to determine the appropriate value, MM, to use for size and
8295: MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8296: to determine the value, BMM to use for bsize
8298: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8299: @*/
8300: PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8301: {
8304: MatStashSetInitialSize_Private(&mat->stash, size);
8305: MatStashSetInitialSize_Private(&mat->bstash, bsize);
8306: return 0;
8307: }
8309: /*@
8310: MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8311: the matrix
8313: Neighbor-wise Collective
8315: Input Parameters:
8316: + mat - the matrix
8317: . x,y - the vectors
8318: - w - where the result is stored
8320: Level: intermediate
8322: Notes:
8323: `w` may be the same vector as `y`.
8325: This allows one to use either the restriction or interpolation (its transpose)
8326: matrix to do the interpolation
8328: .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8329: @*/
8330: PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8331: {
8332: PetscInt M, N, Ny;
8338: MatGetSize(A, &M, &N);
8339: VecGetSize(y, &Ny);
8340: if (M == Ny) {
8341: MatMultAdd(A, x, y, w);
8342: } else {
8343: MatMultTransposeAdd(A, x, y, w);
8344: }
8345: return 0;
8346: }
8348: /*@
8349: MatInterpolate - y = A*x or A'*x depending on the shape of
8350: the matrix
8352: Neighbor-wise Collective
8354: Input Parameters:
8355: + mat - the matrix
8356: - x,y - the vectors
8358: Level: intermediate
8360: Note:
8361: This allows one to use either the restriction or interpolation (its transpose)
8362: matrix to do the interpolation
8364: .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8365: @*/
8366: PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8367: {
8368: PetscInt M, N, Ny;
8373: MatGetSize(A, &M, &N);
8374: VecGetSize(y, &Ny);
8375: if (M == Ny) {
8376: MatMult(A, x, y);
8377: } else {
8378: MatMultTranspose(A, x, y);
8379: }
8380: return 0;
8381: }
8383: /*@
8384: MatRestrict - y = A*x or A'*x
8386: Neighbor-wise Collective on Mat
8388: Input Parameters:
8389: + mat - the matrix
8390: - x,y - the vectors
8392: Level: intermediate
8394: Note:
8395: This allows one to use either the restriction or interpolation (its transpose)
8396: matrix to do the restriction
8398: .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8399: @*/
8400: PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8401: {
8402: PetscInt M, N, Ny;
8407: MatGetSize(A, &M, &N);
8408: VecGetSize(y, &Ny);
8409: if (M == Ny) {
8410: MatMult(A, x, y);
8411: } else {
8412: MatMultTranspose(A, x, y);
8413: }
8414: return 0;
8415: }
8417: /*@
8418: MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8420: Neighbor-wise Collective on Mat
8422: Input Parameters:
8423: + mat - the matrix
8424: - w, x - the input dense matrices
8426: Output Parameters:
8427: . y - the output dense matrix
8429: Level: intermediate
8431: Note:
8432: This allows one to use either the restriction or interpolation (its transpose)
8433: matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8434: otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8436: .seealso: `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8437: @*/
8438: PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8439: {
8440: PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8441: PetscBool trans = PETSC_TRUE;
8442: MatReuse reuse = MAT_INITIAL_MATRIX;
8449: MatGetSize(A, &M, &N);
8450: MatGetSize(x, &Mx, &Nx);
8451: if (N == Mx) trans = PETSC_FALSE;
8453: Mo = trans ? N : M;
8454: if (*y) {
8455: MatGetSize(*y, &My, &Ny);
8456: if (Mo == My && Nx == Ny) {
8457: reuse = MAT_REUSE_MATRIX;
8458: } else {
8460: MatDestroy(y);
8461: }
8462: }
8464: if (w && *y == w) { /* this is to minimize changes in PCMG */
8465: PetscBool flg;
8467: PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w);
8468: if (w) {
8469: PetscInt My, Ny, Mw, Nw;
8471: PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg);
8472: MatGetSize(*y, &My, &Ny);
8473: MatGetSize(w, &Mw, &Nw);
8474: if (!flg || My != Mw || Ny != Nw) w = NULL;
8475: }
8476: if (!w) {
8477: MatDuplicate(*y, MAT_COPY_VALUES, &w);
8478: PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w);
8479: PetscObjectDereference((PetscObject)w);
8480: } else {
8481: MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN);
8482: }
8483: }
8484: if (!trans) {
8485: MatMatMult(A, x, reuse, PETSC_DEFAULT, y);
8486: } else {
8487: MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y);
8488: }
8489: if (w) MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN);
8490: return 0;
8491: }
8493: /*@
8494: MatMatInterpolate - Y = A*X or A'*X
8496: Neighbor-wise Collective on Mat
8498: Input Parameters:
8499: + mat - the matrix
8500: - x - the input dense matrix
8502: Output Parameters:
8503: . y - the output dense matrix
8505: Level: intermediate
8507: Note:
8508: This allows one to use either the restriction or interpolation (its transpose)
8509: matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8510: otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8512: .seealso: `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8513: @*/
8514: PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8515: {
8516: MatMatInterpolateAdd(A, x, NULL, y);
8517: return 0;
8518: }
8520: /*@
8521: MatMatRestrict - Y = A*X or A'*X
8523: Neighbor-wise Collective on Mat
8525: Input Parameters:
8526: + mat - the matrix
8527: - x - the input dense matrix
8529: Output Parameters:
8530: . y - the output dense matrix
8532: Level: intermediate
8534: Note:
8535: This allows one to use either the restriction or interpolation (its transpose)
8536: matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8537: otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8539: .seealso: `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8540: @*/
8541: PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8542: {
8543: MatMatInterpolateAdd(A, x, NULL, y);
8544: return 0;
8545: }
8547: /*@
8548: MatGetNullSpace - retrieves the null space of a matrix.
8550: Logically Collective
8552: Input Parameters:
8553: + mat - the matrix
8554: - nullsp - the null space object
8556: Level: developer
8558: .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8559: @*/
8560: PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8561: {
8564: *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8565: return 0;
8566: }
8568: /*@
8569: MatSetNullSpace - attaches a null space to a matrix.
8571: Logically Collective
8573: Input Parameters:
8574: + mat - the matrix
8575: - nullsp - the null space object
8577: Level: advanced
8579: Notes:
8580: This null space is used by the `KSP` linear solvers to solve singular systems.
8582: 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`
8584: 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
8585: to zero but the linear system will still be solved in a least squares sense.
8587: The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8588: 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).
8589: 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
8590: 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
8591: 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).
8592: This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8594: If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8595: `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8596: routine also automatically calls `MatSetTransposeNullSpace()`.
8598: The user should call `MatNullSpaceDestroy()`.
8600: .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8601: `KSPSetPCSide()`
8602: @*/
8603: PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8604: {
8607: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8608: MatNullSpaceDestroy(&mat->nullsp);
8609: mat->nullsp = nullsp;
8610: if (mat->symmetric == PETSC_BOOL3_TRUE) MatSetTransposeNullSpace(mat, nullsp);
8611: return 0;
8612: }
8614: /*@
8615: MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8617: Logically Collective
8619: Input Parameters:
8620: + mat - the matrix
8621: - nullsp - the null space object
8623: Level: developer
8625: .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8626: @*/
8627: PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8628: {
8632: *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8633: return 0;
8634: }
8636: /*@
8637: MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8639: Logically Collective
8641: Input Parameters:
8642: + mat - the matrix
8643: - nullsp - the null space object
8645: Level: advanced
8647: Notes:
8648: This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8650: See `MatSetNullSpace()`
8652: .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8653: @*/
8654: PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8655: {
8658: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8659: MatNullSpaceDestroy(&mat->transnullsp);
8660: mat->transnullsp = nullsp;
8661: return 0;
8662: }
8664: /*@
8665: MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8666: This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8668: Logically Collective
8670: Input Parameters:
8671: + mat - the matrix
8672: - nullsp - the null space object
8674: Level: advanced
8676: Notes:
8677: Overwrites any previous near null space that may have been attached
8679: You can remove the null space by calling this routine with an nullsp of `NULL`
8681: .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8682: @*/
8683: PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8684: {
8688: MatCheckPreallocated(mat, 1);
8689: if (nullsp) PetscObjectReference((PetscObject)nullsp);
8690: MatNullSpaceDestroy(&mat->nearnullsp);
8691: mat->nearnullsp = nullsp;
8692: return 0;
8693: }
8695: /*@
8696: MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8698: Not Collective
8700: Input Parameter:
8701: . mat - the matrix
8703: Output Parameter:
8704: . nullsp - the null space object, `NULL` if not set
8706: Level: advanced
8708: .seealso: `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8709: @*/
8710: PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8711: {
8715: MatCheckPreallocated(mat, 1);
8716: *nullsp = mat->nearnullsp;
8717: return 0;
8718: }
8720: /*@C
8721: MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8723: Collective
8725: Input Parameters:
8726: + mat - the matrix
8727: . row - row/column permutation
8728: . fill - expected fill factor >= 1.0
8729: - level - level of fill, for ICC(k)
8731: Notes:
8732: Probably really in-place only when level of fill is zero, otherwise allocates
8733: new space to store factored matrix and deletes previous memory.
8735: Most users should employ the `KSP` interface for linear solvers
8736: instead of working directly with matrix algebra routines such as this.
8737: See, e.g., `KSPCreate()`.
8739: Level: developer
8741: Developer Note:
8742: The Fortran interface is not autogenerated as the
8743: interface definition cannot be generated correctly [due to `MatFactorInfo`]
8745: .seealso: `Mat`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8746: @*/
8747: PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8748: {
8756: MatCheckPreallocated(mat, 1);
8757: PetscUseTypeMethod(mat, iccfactor, row, info);
8758: PetscObjectStateIncrease((PetscObject)mat);
8759: return 0;
8760: }
8762: /*@
8763: MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8764: ghosted ones.
8766: Not Collective
8768: Input Parameters:
8769: + mat - the matrix
8770: - diag - the diagonal values, including ghost ones
8772: Level: developer
8774: Notes:
8775: Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8777: This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8779: .seealso: `Mat`, `MatDiagonalScale()`
8780: @*/
8781: PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8782: {
8783: PetscMPIInt size;
8790: PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
8791: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8792: if (size == 1) {
8793: PetscInt n, m;
8794: VecGetSize(diag, &n);
8795: MatGetSize(mat, NULL, &m);
8796: if (m == n) {
8797: MatDiagonalScale(mat, NULL, diag);
8798: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8799: } else {
8800: PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8801: }
8802: PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
8803: PetscObjectStateIncrease((PetscObject)mat);
8804: return 0;
8805: }
8807: /*@
8808: MatGetInertia - Gets the inertia from a factored matrix
8810: Collective
8812: Input Parameter:
8813: . mat - the matrix
8815: Output Parameters:
8816: + nneg - number of negative eigenvalues
8817: . nzero - number of zero eigenvalues
8818: - npos - number of positive eigenvalues
8820: Level: advanced
8822: Note:
8823: Matrix must have been factored by `MatCholeskyFactor()`
8825: .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
8826: @*/
8827: PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8828: {
8833: PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8834: return 0;
8835: }
8837: /*@C
8838: MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8840: Neighbor-wise Collective
8842: Input Parameters:
8843: + mat - the factored matrix obtained with `MatGetFactor()`
8844: - b - the right-hand-side vectors
8846: Output Parameter:
8847: . x - the result vectors
8849: Level: developer
8851: Note:
8852: The vectors `b` and `x` cannot be the same. I.e., one cannot
8853: call `MatSolves`(A,x,x).
8855: .seealso: `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8856: @*/
8857: PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
8858: {
8863: if (!mat->rmap->N && !mat->cmap->N) return 0;
8865: MatCheckPreallocated(mat, 1);
8866: PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0);
8867: PetscUseTypeMethod(mat, solves, b, x);
8868: PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0);
8869: return 0;
8870: }
8872: /*@
8873: MatIsSymmetric - Test whether a matrix is symmetric
8875: Collective
8877: Input Parameters:
8878: + A - the matrix to test
8879: - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
8881: Output Parameters:
8882: . flg - the result
8884: Level: intermediate
8886: Notes:
8887: For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8889: If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
8891: One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8892: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8894: .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
8895: `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8896: @*/
8897: PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
8898: {
8902: if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8903: else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8904: else {
8905: if (!A->ops->issymmetric) {
8906: MatType mattype;
8907: MatGetType(A, &mattype);
8908: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8909: }
8910: PetscUseTypeMethod(A, issymmetric, tol, flg);
8911: if (!tol) MatSetOption(A, MAT_SYMMETRIC, *flg);
8912: }
8913: return 0;
8914: }
8916: /*@
8917: MatIsHermitian - Test whether a matrix is Hermitian
8919: Collective on Mat
8921: Input Parameters:
8922: + A - the matrix to test
8923: - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
8925: Output Parameters:
8926: . flg - the result
8928: Level: intermediate
8930: Notes:
8931: For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8933: If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
8935: One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8936: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
8938: .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8939: `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8940: @*/
8941: PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
8942: {
8946: if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8947: else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8948: else {
8949: if (!A->ops->ishermitian) {
8950: MatType mattype;
8951: MatGetType(A, &mattype);
8952: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8953: }
8954: PetscUseTypeMethod(A, ishermitian, tol, flg);
8955: if (!tol) MatSetOption(A, MAT_HERMITIAN, *flg);
8956: }
8957: return 0;
8958: }
8960: /*@
8961: MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
8963: Not Collective
8965: Input Parameter:
8966: . A - the matrix to check
8968: Output Parameters:
8969: + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
8970: - flg - the result (only valid if set is `PETSC_TRUE`)
8972: Level: advanced
8974: Notes:
8975: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
8976: if you want it explicitly checked
8978: One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8979: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8981: .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8982: @*/
8983: PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
8984: {
8988: if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8989: *set = PETSC_TRUE;
8990: *flg = PetscBool3ToBool(A->symmetric);
8991: } else {
8992: *set = PETSC_FALSE;
8993: }
8994: return 0;
8995: }
8997: /*@
8998: MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9000: Not Collective
9002: Input Parameter:
9003: . A - the matrix to check
9005: Output Parameters:
9006: + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9007: - flg - the result (only valid if set is `PETSC_TRUE`)
9009: Level: advanced
9011: Notes:
9012: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9014: One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9015: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9017: .seealso: `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9018: @*/
9019: PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9020: {
9024: if (A->spd != PETSC_BOOL3_UNKNOWN) {
9025: *set = PETSC_TRUE;
9026: *flg = PetscBool3ToBool(A->spd);
9027: } else {
9028: *set = PETSC_FALSE;
9029: }
9030: return 0;
9031: }
9033: /*@
9034: MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9036: Not Collective
9038: Input Parameter:
9039: . A - the matrix to check
9041: Output Parameters:
9042: + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9043: - flg - the result (only valid if set is `PETSC_TRUE`)
9045: Level: advanced
9047: Notes:
9048: Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9049: if you want it explicitly checked
9051: One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9052: after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9054: .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9055: @*/
9056: PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9057: {
9061: if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9062: *set = PETSC_TRUE;
9063: *flg = PetscBool3ToBool(A->hermitian);
9064: } else {
9065: *set = PETSC_FALSE;
9066: }
9067: return 0;
9068: }
9070: /*@
9071: MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9073: Collective on Mat
9075: Input Parameter:
9076: . A - the matrix to test
9078: Output Parameters:
9079: . flg - the result
9081: Level: intermediate
9083: Notes:
9084: If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9086: 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
9087: symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9089: .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9090: @*/
9091: PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9092: {
9095: if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9096: *flg = PetscBool3ToBool(A->structurally_symmetric);
9097: } else {
9098: PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9099: MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg);
9100: }
9101: return 0;
9102: }
9104: /*@
9105: MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9107: Not Collective
9109: Input Parameter:
9110: . A - the matrix to check
9112: Output Parameters:
9113: + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9114: - flg - the result (only valid if set is PETSC_TRUE)
9116: Level: advanced
9118: Notes:
9119: 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
9120: symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9122: Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9124: .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9125: @*/
9126: PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9127: {
9131: if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9132: *set = PETSC_TRUE;
9133: *flg = PetscBool3ToBool(A->structurally_symmetric);
9134: } else {
9135: *set = PETSC_FALSE;
9136: }
9137: return 0;
9138: }
9140: /*@
9141: MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9142: to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9144: Not collective
9146: Input Parameter:
9147: . mat - the matrix
9149: Output Parameters:
9150: + nstash - the size of the stash
9151: . reallocs - the number of additional mallocs incurred.
9152: . bnstash - the size of the block stash
9153: - breallocs - the number of additional mallocs incurred.in the block stash
9155: Level: advanced
9157: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9158: @*/
9159: PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9160: {
9161: MatStashGetInfo_Private(&mat->stash, nstash, reallocs);
9162: MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs);
9163: return 0;
9164: }
9166: /*@C
9167: MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9168: parallel layout, `PetscLayout` for rows and columns
9170: Collective
9172: Input Parameter:
9173: . mat - the matrix
9175: Output Parameters:
9176: + right - (optional) vector that the matrix can be multiplied against
9177: - left - (optional) vector that the matrix vector product can be stored in
9179: Level: advanced
9181: Notes:
9182: 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()`.
9184: These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9186: .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9187: @*/
9188: PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9189: {
9192: if (mat->ops->getvecs) {
9193: PetscUseTypeMethod(mat, getvecs, right, left);
9194: } else {
9195: PetscInt rbs, cbs;
9196: MatGetBlockSizes(mat, &rbs, &cbs);
9197: if (right) {
9199: VecCreate(PetscObjectComm((PetscObject)mat), right);
9200: VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE);
9201: VecSetBlockSize(*right, cbs);
9202: VecSetType(*right, mat->defaultvectype);
9203: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9204: if (mat->boundtocpu && mat->bindingpropagates) {
9205: VecSetBindingPropagates(*right, PETSC_TRUE);
9206: VecBindToCPU(*right, PETSC_TRUE);
9207: }
9208: #endif
9209: PetscLayoutReference(mat->cmap, &(*right)->map);
9210: }
9211: if (left) {
9213: VecCreate(PetscObjectComm((PetscObject)mat), left);
9214: VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE);
9215: VecSetBlockSize(*left, rbs);
9216: VecSetType(*left, mat->defaultvectype);
9217: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9218: if (mat->boundtocpu && mat->bindingpropagates) {
9219: VecSetBindingPropagates(*left, PETSC_TRUE);
9220: VecBindToCPU(*left, PETSC_TRUE);
9221: }
9222: #endif
9223: PetscLayoutReference(mat->rmap, &(*left)->map);
9224: }
9225: }
9226: return 0;
9227: }
9229: /*@C
9230: MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9231: with default values.
9233: Not Collective
9235: Input Parameters:
9236: . info - the `MatFactorInfo` data structure
9238: Level: developer
9240: Notes:
9241: The solvers are generally used through the `KSP` and `PC` objects, for example
9242: `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9244: Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9246: Developer Note:
9247: The Fortran interface is not autogenerated as the
9248: interface definition cannot be generated correctly [due to `MatFactorInfo`]
9250: .seealso: `Mat`, `MatGetFactor()`, `MatFactorInfo`
9251: @*/
9252: PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9253: {
9254: PetscMemzero(info, sizeof(MatFactorInfo));
9255: return 0;
9256: }
9258: /*@
9259: MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9261: Collective
9263: Input Parameters:
9264: + mat - the factored matrix
9265: - is - the index set defining the Schur indices (0-based)
9267: Level: advanced
9269: Notes:
9270: Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9272: You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9274: This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9276: .seealso: `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9277: `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9278: @*/
9279: PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9280: {
9281: PetscErrorCode (*f)(Mat, IS);
9289: PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f);
9291: MatDestroy(&mat->schur);
9292: (*f)(mat, is);
9294: return 0;
9295: }
9297: /*@
9298: MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9300: Logically Collective
9302: Input Parameters:
9303: + F - the factored matrix obtained by calling `MatGetFactor()`
9304: . S - location where to return the Schur complement, can be `NULL`
9305: - status - the status of the Schur complement matrix, can be `NULL`
9307: Level: advanced
9309: Notes:
9310: You must call `MatFactorSetSchurIS()` before calling this routine.
9312: This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9314: The routine provides a copy of the Schur matrix stored within the solver data structures.
9315: The caller must destroy the object when it is no longer needed.
9316: If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9318: 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)
9320: See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9322: Developer Note:
9323: The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9324: matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9326: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9327: @*/
9328: PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9329: {
9333: if (S) {
9334: PetscErrorCode (*f)(Mat, Mat *);
9336: PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f);
9337: if (f) {
9338: (*f)(F, S);
9339: } else {
9340: MatDuplicate(F->schur, MAT_COPY_VALUES, S);
9341: }
9342: }
9343: if (status) *status = F->schur_status;
9344: return 0;
9345: }
9347: /*@
9348: MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9350: Logically Collective
9352: Input Parameters:
9353: + F - the factored matrix obtained by calling `MatGetFactor()`
9354: . *S - location where to return the Schur complement, can be `NULL`
9355: - status - the status of the Schur complement matrix, can be `NULL`
9357: Level: advanced
9359: Notes:
9360: You must call `MatFactorSetSchurIS()` before calling this routine.
9362: Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9364: The routine returns a the Schur Complement stored within the data structures of the solver.
9366: If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9368: The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9370: Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9372: See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9374: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9375: @*/
9376: PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9377: {
9381: if (S) *S = F->schur;
9382: if (status) *status = F->schur_status;
9383: return 0;
9384: }
9386: /*@
9387: MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9389: Logically Collective
9391: Input Parameters:
9392: + F - the factored matrix obtained by calling `MatGetFactor()`
9393: . *S - location where the Schur complement is stored
9394: - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9396: Level: advanced
9398: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9399: @*/
9400: PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9401: {
9403: if (S) {
9405: *S = NULL;
9406: }
9407: F->schur_status = status;
9408: MatFactorUpdateSchurStatus_Private(F);
9409: return 0;
9410: }
9412: /*@
9413: MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9415: Logically Collective
9417: Input Parameters:
9418: + F - the factored matrix obtained by calling `MatGetFactor()`
9419: . rhs - location where the right hand side of the Schur complement system is stored
9420: - sol - location where the solution of the Schur complement system has to be returned
9422: Level: advanced
9424: Notes:
9425: The sizes of the vectors should match the size of the Schur complement
9427: Must be called after `MatFactorSetSchurIS()`
9429: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9430: @*/
9431: PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9432: {
9441: MatFactorFactorizeSchurComplement(F);
9442: switch (F->schur_status) {
9443: case MAT_FACTOR_SCHUR_FACTORED:
9444: MatSolveTranspose(F->schur, rhs, sol);
9445: break;
9446: case MAT_FACTOR_SCHUR_INVERTED:
9447: MatMultTranspose(F->schur, rhs, sol);
9448: break;
9449: default:
9450: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9451: }
9452: return 0;
9453: }
9455: /*@
9456: MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9458: Logically Collective
9460: Input Parameters:
9461: + F - the factored matrix obtained by calling `MatGetFactor()`
9462: . rhs - location where the right hand side of the Schur complement system is stored
9463: - sol - location where the solution of the Schur complement system has to be returned
9465: Level: advanced
9467: Notes:
9468: The sizes of the vectors should match the size of the Schur complement
9470: Must be called after `MatFactorSetSchurIS()`
9472: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9473: @*/
9474: PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9475: {
9484: MatFactorFactorizeSchurComplement(F);
9485: switch (F->schur_status) {
9486: case MAT_FACTOR_SCHUR_FACTORED:
9487: MatSolve(F->schur, rhs, sol);
9488: break;
9489: case MAT_FACTOR_SCHUR_INVERTED:
9490: MatMult(F->schur, rhs, sol);
9491: break;
9492: default:
9493: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9494: }
9495: return 0;
9496: }
9498: /*@
9499: MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9501: Logically Collective on F
9503: Input Parameters:
9504: . F - the factored matrix obtained by calling `MatGetFactor()`
9506: Level: advanced
9508: Notes:
9509: Must be called after `MatFactorSetSchurIS()`.
9511: Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9513: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9514: @*/
9515: PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9516: {
9519: if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) return 0;
9520: MatFactorFactorizeSchurComplement(F);
9521: MatFactorInvertSchurComplement_Private(F);
9522: F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9523: return 0;
9524: }
9526: /*@
9527: MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9529: Logically Collective
9531: Input Parameters:
9532: . F - the factored matrix obtained by calling `MatGetFactor()`
9534: Level: advanced
9536: Note:
9537: Must be called after `MatFactorSetSchurIS()`
9539: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9540: @*/
9541: PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9542: {
9545: if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) return 0;
9546: MatFactorFactorizeSchurComplement_Private(F);
9547: F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9548: return 0;
9549: }
9551: /*@
9552: MatPtAP - Creates the matrix product C = P^T * A * P
9554: Neighbor-wise Collective
9556: Input Parameters:
9557: + A - the matrix
9558: . P - the projection matrix
9559: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9560: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9561: if the result is a dense matrix this is irrelevant
9563: Output Parameters:
9564: . C - the product matrix
9566: Level: intermediate
9568: Notes:
9569: C will be created and must be destroyed by the user with `MatDestroy()`.
9571: An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9573: Developer Note:
9574: For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9576: .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9577: @*/
9578: PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9579: {
9580: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9583: if (scall == MAT_INITIAL_MATRIX) {
9584: MatProductCreate(A, P, NULL, C);
9585: MatProductSetType(*C, MATPRODUCT_PtAP);
9586: MatProductSetAlgorithm(*C, "default");
9587: MatProductSetFill(*C, fill);
9589: (*C)->product->api_user = PETSC_TRUE;
9590: MatProductSetFromOptions(*C);
9592: MatProductSymbolic(*C);
9593: } else { /* scall == MAT_REUSE_MATRIX */
9594: MatProductReplaceMats(A, P, NULL, *C);
9595: }
9597: MatProductNumeric(*C);
9598: (*C)->symmetric = A->symmetric;
9599: (*C)->spd = A->spd;
9600: return 0;
9601: }
9603: /*@
9604: MatRARt - Creates the matrix product C = R * A * R^T
9606: Neighbor-wise Collective
9608: Input Parameters:
9609: + A - the matrix
9610: . R - the projection matrix
9611: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9612: - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9613: if the result is a dense matrix this is irrelevant
9615: Output Parameters:
9616: . C - the product matrix
9618: Level: intermediate
9620: Notes:
9621: C will be created and must be destroyed by the user with `MatDestroy()`.
9623: An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9625: This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9626: which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9627: parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9628: We recommend using MatPtAP().
9630: .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9631: @*/
9632: PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9633: {
9634: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9637: if (scall == MAT_INITIAL_MATRIX) {
9638: MatProductCreate(A, R, NULL, C);
9639: MatProductSetType(*C, MATPRODUCT_RARt);
9640: MatProductSetAlgorithm(*C, "default");
9641: MatProductSetFill(*C, fill);
9643: (*C)->product->api_user = PETSC_TRUE;
9644: MatProductSetFromOptions(*C);
9646: MatProductSymbolic(*C);
9647: } else { /* scall == MAT_REUSE_MATRIX */
9648: MatProductReplaceMats(A, R, NULL, *C);
9649: }
9651: MatProductNumeric(*C);
9652: if (A->symmetric == PETSC_BOOL3_TRUE) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9653: return 0;
9654: }
9656: static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9657: {
9660: if (scall == MAT_INITIAL_MATRIX) {
9661: PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]);
9662: MatProductCreate(A, B, NULL, C);
9663: MatProductSetType(*C, ptype);
9664: MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT);
9665: MatProductSetFill(*C, fill);
9667: (*C)->product->api_user = PETSC_TRUE;
9668: MatProductSetFromOptions(*C);
9669: MatProductSymbolic(*C);
9670: } else { /* scall == MAT_REUSE_MATRIX */
9671: Mat_Product *product = (*C)->product;
9672: PetscBool isdense;
9674: PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "");
9675: if (isdense && product && product->type != ptype) {
9676: MatProductClear(*C);
9677: product = NULL;
9678: }
9679: PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]);
9680: if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9681: if (isdense) {
9682: MatProductCreate_Private(A, B, NULL, *C);
9683: product = (*C)->product;
9684: product->fill = fill;
9685: product->api_user = PETSC_TRUE;
9686: product->clear = PETSC_TRUE;
9688: MatProductSetType(*C, ptype);
9689: MatProductSetFromOptions(*C);
9691: MatProductSymbolic(*C);
9692: } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9693: } else { /* user may change input matrices A or B when REUSE */
9694: MatProductReplaceMats(A, B, NULL, *C);
9695: }
9696: }
9697: MatProductNumeric(*C);
9698: return 0;
9699: }
9701: /*@
9702: MatMatMult - Performs matrix-matrix multiplication C=A*B.
9704: Neighbor-wise Collective
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 you do not have a good estimate
9711: if the result is a dense matrix this is irrelevant
9713: Output Parameters:
9714: . C - the product matrix
9716: Notes:
9717: Unless scall is `MAT_REUSE_MATRIX` C will be created.
9719: `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
9720: call to this function with `MAT_INITIAL_MATRIX`.
9722: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9724: 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`,
9725: rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9727: Example of Usage:
9728: .vb
9729: MatProductCreate(A,B,NULL,&C);
9730: MatProductSetType(C,MATPRODUCT_AB);
9731: MatProductSymbolic(C);
9732: MatProductNumeric(C); // compute C=A * B
9733: MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9734: MatProductNumeric(C);
9735: MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9736: MatProductNumeric(C);
9737: .ve
9739: Level: intermediate
9741: .seealso: `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9742: @*/
9743: PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9744: {
9745: MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C);
9746: return 0;
9747: }
9749: /*@
9750: MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9752: Neighbor-wise Collective
9754: Input Parameters:
9755: + A - the left matrix
9756: . B - the right matrix
9757: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9758: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9760: Output Parameters:
9761: . C - the product matrix
9763: Level: intermediate
9765: Notes:
9766: C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9768: `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9770: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9771: actually needed.
9773: This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9774: and for pairs of `MATMPIDENSE` matrices.
9776: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
9778: Options Database Keys:
9779: . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9780: first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9781: the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9783: .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9784: @*/
9785: PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9786: {
9787: MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C);
9788: if (A == B) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9789: return 0;
9790: }
9792: /*@
9793: MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
9795: Neighbor-wise Collective
9797: Input Parameters:
9798: + A - the left matrix
9799: . B - the right matrix
9800: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9801: - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9803: Output Parameters:
9804: . C - the product matrix
9806: Level: intermediate
9808: Notes:
9809: C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9811: `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9813: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
9815: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9816: actually needed.
9818: This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9819: which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices.
9821: .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9822: @*/
9823: PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9824: {
9825: MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C);
9826: return 0;
9827: }
9829: /*@
9830: MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
9832: Neighbor-wise Collective
9834: Input Parameters:
9835: + A - the left matrix
9836: . B - the middle matrix
9837: . C - the right matrix
9838: . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9839: - 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
9840: if the result is a dense matrix this is irrelevant
9842: Output Parameters:
9843: . D - the product matrix
9845: Level: intermediate
9847: Notes:
9848: Unless scall is `MAT_REUSE_MATRIX` D will be created.
9850: `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9852: This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
9854: To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9855: actually needed.
9857: If you have many matrices with the same non-zero structure to multiply, you
9858: should use `MAT_REUSE_MATRIX` in all calls but the first
9860: .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9861: @*/
9862: PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
9863: {
9864: if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
9867: if (scall == MAT_INITIAL_MATRIX) {
9868: MatProductCreate(A, B, C, D);
9869: MatProductSetType(*D, MATPRODUCT_ABC);
9870: MatProductSetAlgorithm(*D, "default");
9871: MatProductSetFill(*D, fill);
9873: (*D)->product->api_user = PETSC_TRUE;
9874: MatProductSetFromOptions(*D);
9876: ((PetscObject)C)->type_name);
9877: MatProductSymbolic(*D);
9878: } else { /* user may change input matrices when REUSE */
9879: MatProductReplaceMats(A, B, C, *D);
9880: }
9881: MatProductNumeric(*D);
9882: return 0;
9883: }
9885: /*@
9886: MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9888: Collective
9890: Input Parameters:
9891: + mat - the matrix
9892: . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9893: . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
9894: - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9896: Output Parameter:
9897: . matredundant - redundant matrix
9899: Level: advanced
9901: Notes:
9902: `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
9903: original matrix has not changed from that last call to MatCreateRedundantMatrix().
9905: This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9906: calling it.
9908: `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
9910: .seealso: `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
9911: @*/
9912: PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
9913: {
9914: MPI_Comm comm;
9915: PetscMPIInt size;
9916: PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9917: Mat_Redundant *redund = NULL;
9918: PetscSubcomm psubcomm = NULL;
9919: MPI_Comm subcomm_in = subcomm;
9920: Mat *matseq;
9921: IS isrow, iscol;
9922: PetscBool newsubcomm = PETSC_FALSE;
9925: if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9928: }
9930: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
9931: if (size == 1 || nsubcomm == 1) {
9932: if (reuse == MAT_INITIAL_MATRIX) {
9933: MatDuplicate(mat, MAT_COPY_VALUES, matredundant);
9934: } else {
9936: MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN);
9937: }
9938: return 0;
9939: }
9943: MatCheckPreallocated(mat, 1);
9945: PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0);
9946: if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9947: /* create psubcomm, then get subcomm */
9948: PetscObjectGetComm((PetscObject)mat, &comm);
9949: MPI_Comm_size(comm, &size);
9952: PetscSubcommCreate(comm, &psubcomm);
9953: PetscSubcommSetNumber(psubcomm, nsubcomm);
9954: PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS);
9955: PetscSubcommSetFromOptions(psubcomm);
9956: PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL);
9957: newsubcomm = PETSC_TRUE;
9958: PetscSubcommDestroy(&psubcomm);
9959: }
9961: /* get isrow, iscol and a local sequential matrix matseq[0] */
9962: if (reuse == MAT_INITIAL_MATRIX) {
9963: mloc_sub = PETSC_DECIDE;
9964: nloc_sub = PETSC_DECIDE;
9965: if (bs < 1) {
9966: PetscSplitOwnership(subcomm, &mloc_sub, &M);
9967: PetscSplitOwnership(subcomm, &nloc_sub, &N);
9968: } else {
9969: PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M);
9970: PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N);
9971: }
9972: MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm);
9973: rstart = rend - mloc_sub;
9974: ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow);
9975: ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol);
9976: } else { /* reuse == MAT_REUSE_MATRIX */
9978: /* retrieve subcomm */
9979: PetscObjectGetComm((PetscObject)(*matredundant), &subcomm);
9980: redund = (*matredundant)->redundant;
9981: isrow = redund->isrow;
9982: iscol = redund->iscol;
9983: matseq = redund->matseq;
9984: }
9985: MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq);
9987: /* get matredundant over subcomm */
9988: if (reuse == MAT_INITIAL_MATRIX) {
9989: MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant);
9991: /* create a supporting struct and attach it to C for reuse */
9992: PetscNew(&redund);
9993: (*matredundant)->redundant = redund;
9994: redund->isrow = isrow;
9995: redund->iscol = iscol;
9996: redund->matseq = matseq;
9997: if (newsubcomm) {
9998: redund->subcomm = subcomm;
9999: } else {
10000: redund->subcomm = MPI_COMM_NULL;
10001: }
10002: } else {
10003: MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant);
10004: }
10005: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10006: if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10007: MatBindToCPU(*matredundant, PETSC_TRUE);
10008: MatSetBindingPropagates(*matredundant, PETSC_TRUE);
10009: }
10010: #endif
10011: PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0);
10012: return 0;
10013: }
10015: /*@C
10016: MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10017: a given `Mat`. Each submatrix can span multiple procs.
10019: Collective
10021: Input Parameters:
10022: + mat - the matrix
10023: . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10024: - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10026: Output Parameter:
10027: . subMat - parallel sub-matrices each spanning a given `subcomm`
10029: Level: advanced
10031: Notes:
10032: The submatrix partition across processors is dictated by `subComm` a
10033: communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10034: is not restricted to be grouped with consecutive original ranks.
10036: Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10037: map directly to the layout of the original matrix [wrt the local
10038: row,col partitioning]. So the original 'DiagonalMat' naturally maps
10039: into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10040: the `subMat`. However the offDiagMat looses some columns - and this is
10041: reconstructed with `MatSetValues()`
10043: This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10045: .seealso: `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10046: @*/
10047: PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10048: {
10049: PetscMPIInt commsize, subCommSize;
10051: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize);
10052: MPI_Comm_size(subComm, &subCommSize);
10056: PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10057: PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10058: PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10059: return 0;
10060: }
10062: /*@
10063: MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10065: Not Collective
10067: Input Parameters:
10068: + mat - matrix to extract local submatrix from
10069: . isrow - local row indices for submatrix
10070: - iscol - local column indices for submatrix
10072: Output Parameter:
10073: . submat - the submatrix
10075: Level: intermediate
10077: Notes:
10078: `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10080: Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be
10081: the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10083: `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then
10084: `MatSetValuesBlockedLocal()` will also be implemented.
10086: `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10087: Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10089: .seealso: `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10090: @*/
10091: PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10092: {
10100: if (mat->ops->getlocalsubmatrix) {
10101: PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10102: } else {
10103: MatCreateLocalRef(mat, isrow, iscol, submat);
10104: }
10105: return 0;
10106: }
10108: /*@
10109: MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10111: Not Collective
10113: Input Parameters:
10114: + mat - matrix to extract local submatrix from
10115: . isrow - local row indices for submatrix
10116: . iscol - local column indices for submatrix
10117: - submat - the submatrix
10119: Level: intermediate
10121: .seealso: `Mat`, `MatGetLocalSubMatrix()`
10122: @*/
10123: PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10124: {
10132: if (mat->ops->restorelocalsubmatrix) {
10133: PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10134: } else {
10135: MatDestroy(submat);
10136: }
10137: *submat = NULL;
10138: return 0;
10139: }
10141: /*@
10142: MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10144: Collective
10146: Input Parameter:
10147: . mat - the matrix
10149: Output Parameter:
10150: . is - if any rows have zero diagonals this contains the list of them
10152: Level: developer
10154: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10155: @*/
10156: PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10157: {
10163: if (!mat->ops->findzerodiagonals) {
10164: Vec diag;
10165: const PetscScalar *a;
10166: PetscInt *rows;
10167: PetscInt rStart, rEnd, r, nrow = 0;
10169: MatCreateVecs(mat, &diag, NULL);
10170: MatGetDiagonal(mat, diag);
10171: MatGetOwnershipRange(mat, &rStart, &rEnd);
10172: VecGetArrayRead(diag, &a);
10173: for (r = 0; r < rEnd - rStart; ++r)
10174: if (a[r] == 0.0) ++nrow;
10175: PetscMalloc1(nrow, &rows);
10176: nrow = 0;
10177: for (r = 0; r < rEnd - rStart; ++r)
10178: if (a[r] == 0.0) rows[nrow++] = r + rStart;
10179: VecRestoreArrayRead(diag, &a);
10180: VecDestroy(&diag);
10181: ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is);
10182: } else {
10183: PetscUseTypeMethod(mat, findzerodiagonals, is);
10184: }
10185: return 0;
10186: }
10188: /*@
10189: MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10191: Collective
10193: Input Parameter:
10194: . mat - the matrix
10196: Output Parameter:
10197: . is - contains the list of rows with off block diagonal entries
10199: Level: developer
10201: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10202: @*/
10203: PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10204: {
10210: PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10211: return 0;
10212: }
10214: /*@C
10215: MatInvertBlockDiagonal - Inverts the block diagonal entries.
10217: Collective; No Fortran Support
10219: Input Parameters:
10220: . mat - the matrix
10222: Output Parameters:
10223: . values - the block inverses in column major order (FORTRAN-like)
10225: Level: advanced
10227: Notes:
10228: The size of the blocks is determined by the block size of the matrix.
10230: The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10232: The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10234: .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10235: @*/
10236: PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10237: {
10241: PetscUseTypeMethod(mat, invertblockdiagonal, values);
10242: return 0;
10243: }
10245: /*@C
10246: MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10248: Collective; No Fortran Support
10250: Input Parameters:
10251: + mat - the matrix
10252: . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10253: - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10255: Output Parameters:
10256: . values - the block inverses in column major order (FORTRAN-like)
10258: Level: advanced
10260: Notes:
10261: Use `MatInvertBlockDiagonal()` if all blocks have the same size
10263: The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10265: .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10266: @*/
10267: PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10268: {
10272: PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10273: return 0;
10274: }
10276: /*@
10277: MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10279: Collective on Mat
10281: Input Parameters:
10282: + A - the matrix
10283: - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set.
10285: Level: advanced
10287: Note:
10288: The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10290: .seealso: `Mat`, `MatInvertBlockDiagonal()`
10291: @*/
10292: PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10293: {
10294: const PetscScalar *vals;
10295: PetscInt *dnnz;
10296: PetscInt m, rstart, rend, bs, i, j;
10298: MatInvertBlockDiagonal(A, &vals);
10299: MatGetBlockSize(A, &bs);
10300: MatGetLocalSize(A, &m, NULL);
10301: MatSetLayouts(C, A->rmap, A->cmap);
10302: PetscMalloc1(m / bs, &dnnz);
10303: for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10304: MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL);
10305: PetscFree(dnnz);
10306: MatGetOwnershipRange(C, &rstart, &rend);
10307: MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE);
10308: for (i = rstart / bs; i < rend / bs; i++) MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES);
10309: MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY);
10310: MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY);
10311: MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE);
10312: return 0;
10313: }
10315: /*@C
10316: MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10317: via `MatTransposeColoringCreate()`.
10319: Collective on c
10321: Input Parameter:
10322: . c - coloring context
10324: Level: intermediate
10326: .seealso: `Mat`, `MatTransposeColoringCreate()`
10327: @*/
10328: PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10329: {
10330: MatTransposeColoring matcolor = *c;
10332: if (!matcolor) return 0;
10333: if (--((PetscObject)matcolor)->refct > 0) {
10334: matcolor = NULL;
10335: return 0;
10336: }
10338: PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow);
10339: PetscFree(matcolor->rows);
10340: PetscFree(matcolor->den2sp);
10341: PetscFree(matcolor->colorforcol);
10342: PetscFree(matcolor->columns);
10343: if (matcolor->brows > 0) PetscFree(matcolor->lstart);
10344: PetscHeaderDestroy(c);
10345: return 0;
10346: }
10348: /*@C
10349: MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10350: a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10351: `MatTransposeColoring` to sparse B.
10353: Collective on coloring
10355: Input Parameters:
10356: + B - sparse matrix B
10357: . Btdense - symbolic dense matrix B^T
10358: - coloring - coloring context created with `MatTransposeColoringCreate()`
10360: Output Parameter:
10361: . Btdense - dense matrix B^T
10363: Level: developer
10365: Note:
10366: These are used internally for some implementations of `MatRARt()`
10368: .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10369: @*/
10370: PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10371: {
10376: (B->ops->transcoloringapplysptoden)(coloring, B, Btdense);
10377: return 0;
10378: }
10380: /*@C
10381: MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10382: a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10383: in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10384: Csp from Cden.
10386: Collective
10388: Input Parameters:
10389: + coloring - coloring context created with `MatTransposeColoringCreate()`
10390: - Cden - matrix product of a sparse matrix and a dense matrix Btdense
10392: Output Parameter:
10393: . Csp - sparse matrix
10395: Level: developer
10397: Note:
10398: These are used internally for some implementations of `MatRARt()`
10400: .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10401: @*/
10402: PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10403: {
10408: (Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp);
10409: MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY);
10410: MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY);
10411: return 0;
10412: }
10414: /*@C
10415: MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10417: Collective
10419: Input Parameters:
10420: + mat - the matrix product C
10421: - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10423: Output Parameter:
10424: . color - the new coloring context
10426: Level: intermediate
10428: .seealso: `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10429: `MatTransColoringApplyDenToSp()`
10430: @*/
10431: PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10432: {
10433: MatTransposeColoring c;
10434: MPI_Comm comm;
10436: PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10437: PetscObjectGetComm((PetscObject)mat, &comm);
10438: PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL);
10440: c->ctype = iscoloring->ctype;
10441: if (mat->ops->transposecoloringcreate) {
10442: PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10443: } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10445: *color = c;
10446: PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10447: return 0;
10448: }
10450: /*@
10451: MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10452: matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10453: same, otherwise it will be larger
10455: Not Collective
10457: Input Parameter:
10458: . A - the matrix
10460: Output Parameter:
10461: . state - the current state
10463: Level: intermediate
10465: Notes:
10466: You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10467: different matrices
10469: Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10471: Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10473: .seealso: `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10474: @*/
10475: PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10476: {
10478: *state = mat->nonzerostate;
10479: return 0;
10480: }
10482: /*@
10483: MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10484: matrices from each processor
10486: Collective
10488: Input Parameters:
10489: + comm - the communicators the parallel matrix will live on
10490: . seqmat - the input sequential matrices
10491: . n - number of local columns (or `PETSC_DECIDE`)
10492: - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10494: Output Parameter:
10495: . mpimat - the parallel matrix generated
10497: Level: developer
10499: Note:
10500: The number of columns of the matrix in EACH processor MUST be the same.
10502: .seealso: `Mat`
10503: @*/
10504: PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10505: {
10506: PetscMPIInt size;
10508: MPI_Comm_size(comm, &size);
10509: if (size == 1) {
10510: if (reuse == MAT_INITIAL_MATRIX) {
10511: MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat);
10512: } else {
10513: MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN);
10514: }
10515: return 0;
10516: }
10520: PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0);
10521: (*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat);
10522: PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0);
10523: return 0;
10524: }
10526: /*@
10527: MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10529: Collective
10531: Input Parameters:
10532: + A - the matrix to create subdomains from
10533: - N - requested number of subdomains
10535: Output Parameters:
10536: + n - number of subdomains resulting on this rank
10537: - iss - `IS` list with indices of subdomains on this rank
10539: Level: advanced
10541: Note:
10542: The number of subdomains must be smaller than the communicator size
10544: .seealso: `Mat`, `IS`
10545: @*/
10546: PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10547: {
10548: MPI_Comm comm, subcomm;
10549: PetscMPIInt size, rank, color;
10550: PetscInt rstart, rend, k;
10552: PetscObjectGetComm((PetscObject)A, &comm);
10553: MPI_Comm_size(comm, &size);
10554: MPI_Comm_rank(comm, &rank);
10556: *n = 1;
10557: k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10558: color = rank / k;
10559: MPI_Comm_split(comm, color, rank, &subcomm);
10560: PetscMalloc1(1, iss);
10561: MatGetOwnershipRange(A, &rstart, &rend);
10562: ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]);
10563: MPI_Comm_free(&subcomm);
10564: return 0;
10565: }
10567: /*@
10568: MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10570: If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10571: If they are not the same, uses `MatMatMatMult()`.
10573: Once the coarse grid problem is constructed, correct for interpolation operators
10574: that are not of full rank, which can legitimately happen in the case of non-nested
10575: geometric multigrid.
10577: Input Parameters:
10578: + restrct - restriction operator
10579: . dA - fine grid matrix
10580: . interpolate - interpolation operator
10581: . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10582: - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10584: Output Parameters:
10585: . A - the Galerkin coarse matrix
10587: Options Database Key:
10588: . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10590: Level: developer
10592: .seealso: `Mat`, `MatPtAP()`, `MatMatMatMult()`
10593: @*/
10594: PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10595: {
10596: IS zerorows;
10597: Vec diag;
10600: /* Construct the coarse grid matrix */
10601: if (interpolate == restrct) {
10602: MatPtAP(dA, interpolate, reuse, fill, A);
10603: } else {
10604: MatMatMatMult(restrct, dA, interpolate, reuse, fill, A);
10605: }
10607: /* If the interpolation matrix is not of full rank, A will have zero rows.
10608: This can legitimately happen in the case of non-nested geometric multigrid.
10609: In that event, we set the rows of the matrix to the rows of the identity,
10610: ignoring the equations (as the RHS will also be zero). */
10612: MatFindZeroRows(*A, &zerorows);
10614: if (zerorows != NULL) { /* if there are any zero rows */
10615: MatCreateVecs(*A, &diag, NULL);
10616: MatGetDiagonal(*A, diag);
10617: VecISSet(diag, zerorows, 1.0);
10618: MatDiagonalSet(*A, diag, INSERT_VALUES);
10619: VecDestroy(&diag);
10620: ISDestroy(&zerorows);
10621: }
10622: return 0;
10623: }
10625: /*@C
10626: MatSetOperation - Allows user to set a matrix operation for any matrix type
10628: Logically Collective
10630: Input Parameters:
10631: + mat - the matrix
10632: . op - the name of the operation
10633: - f - the function that provides the operation
10635: Level: developer
10637: Usage:
10638: .vb
10639: extern PetscErrorCode usermult(Mat, Vec, Vec);
10641: MatCreateXXX(comm, ..., &A);
10642: MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult);
10643: .ve
10645: Notes:
10646: See the file `include/petscmat.h` for a complete list of matrix
10647: operations, which all have the form MATOP_<OPERATION>, where
10648: <OPERATION> is the name (in all capital letters) of the
10649: user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10651: All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10652: sequence as the usual matrix interface routines, since they
10653: are intended to be accessed via the usual matrix interface
10654: routines, e.g.,
10655: .vb
10656: MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10657: .ve
10659: In particular each function MUST return `PETSC_SUCCESS` on success and
10660: nonzero on failure.
10662: This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10664: .seealso: `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10665: @*/
10666: PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10667: {
10669: if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10670: (((void (**)(void))mat->ops)[op]) = f;
10671: return 0;
10672: }
10674: /*@C
10675: MatGetOperation - Gets a matrix operation for any matrix type.
10677: Not Collective
10679: Input Parameters:
10680: + mat - the matrix
10681: - op - the name of the operation
10683: Output Parameter:
10684: . f - the function that provides the operation
10686: Level: developer
10688: Usage:
10689: $ PetscErrorCode (*usermult)(Mat,Vec,Vec);
10690: $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10692: Notes:
10693: See the file include/petscmat.h for a complete list of matrix
10694: operations, which all have the form MATOP_<OPERATION>, where
10695: <OPERATION> is the name (in all capital letters) of the
10696: user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10698: This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10700: .seealso: `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10701: @*/
10702: PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10703: {
10705: *f = (((void (**)(void))mat->ops)[op]);
10706: return 0;
10707: }
10709: /*@
10710: MatHasOperation - Determines whether the given matrix supports the particular operation.
10712: Not Collective
10714: Input Parameters:
10715: + mat - the matrix
10716: - op - the operation, for example, `MATOP_GET_DIAGONAL`
10718: Output Parameter:
10719: . has - either `PETSC_TRUE` or `PETSC_FALSE`
10721: Level: advanced
10723: Note:
10724: See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
10726: .seealso: `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10727: @*/
10728: PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10729: {
10732: if (mat->ops->hasoperation) {
10733: PetscUseTypeMethod(mat, hasoperation, op, has);
10734: } else {
10735: if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10736: else {
10737: *has = PETSC_FALSE;
10738: if (op == MATOP_CREATE_SUBMATRIX) {
10739: PetscMPIInt size;
10741: MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
10742: if (size == 1) MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has);
10743: }
10744: }
10745: }
10746: return 0;
10747: }
10749: /*@
10750: MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
10752: Collective
10754: Input Parameters:
10755: . mat - the matrix
10757: Output Parameter:
10758: . cong - either `PETSC_TRUE` or `PETSC_FALSE`
10760: Level: beginner
10762: .seealso: `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10763: @*/
10764: PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10765: {
10769: if (!mat->rmap || !mat->cmap) {
10770: *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10771: return 0;
10772: }
10773: if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10774: PetscLayoutSetUp(mat->rmap);
10775: PetscLayoutSetUp(mat->cmap);
10776: PetscLayoutCompare(mat->rmap, mat->cmap, cong);
10777: if (*cong) mat->congruentlayouts = 1;
10778: else mat->congruentlayouts = 0;
10779: } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10780: return 0;
10781: }
10783: PetscErrorCode MatSetInf(Mat A)
10784: {
10785: PetscUseTypeMethod(A, setinf);
10786: return 0;
10787: }
10789: /*C
10790: 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
10791: and possibly removes small values from the graph structure.
10793: Collective
10795: Input Parameters:
10796: + A - the matrix
10797: . sym - `PETSC_TRUE` indicates that the graph should be symmetrized
10798: . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
10799: - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
10801: Output Parameter:
10802: . graph - the resulting graph
10804: Level: advanced
10806: .seealso: `Mat`, `MatCreate()`, `PCGAMG`
10807: */
10808: PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
10809: {
10813: PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
10814: return 0;
10815: }