Actual source code: matrix.c

  1: /*
  2:    This is where the abstract matrix operations are defined
  3:    Portions of this code are under:
  4:    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
  5: */

  7: #include <petsc/private/matimpl.h>
  8: #include <petsc/private/isimpl.h>
  9: #include <petsc/private/vecimpl.h>

 11: /* Logging support */
 12: PetscClassId MAT_CLASSID;
 13: PetscClassId MAT_COLORING_CLASSID;
 14: PetscClassId MAT_FDCOLORING_CLASSID;
 15: PetscClassId MAT_TRANSPOSECOLORING_CLASSID;

 17: PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
 18: PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
 19: PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
 20: PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
 21: PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
 22: PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
 23: PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
 24: PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
 25: PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
 26: PetscLogEvent MAT_TransposeColoringCreate;
 27: PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
 28: PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
 29: PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
 30: PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
 31: PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
 32: PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
 33: PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
 34: PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
 35: PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
 36: PetscLogEvent MAT_GetMultiProcBlock;
 37: PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
 38: PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
 39: PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
 40: PetscLogEvent MAT_SetValuesBatch;
 41: PetscLogEvent MAT_ViennaCLCopyToGPU;
 42: PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
 43: PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
 44: PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
 45: PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
 46: PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;

 48: const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};

 50: /*@
 51:    MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
 52:                   for sparse matrices that already have locations it fills the locations with random numbers

 54:    Logically Collective on mat

 56:    Input Parameters:
 57: +  x  - the matrix
 58: -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and
 59:           it will create one internally.

 61:    Output Parameter:
 62: .  x  - the matrix

 64:    Example of Usage:
 65: .vb
 66:      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
 67:      MatSetRandom(x,rctx);
 68:      PetscRandomDestroy(rctx);
 69: .ve

 71:    Level: intermediate

 73: .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
 74: @*/
 75: PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
 76: {
 77:   PetscRandom randObj = NULL;

 82:   MatCheckPreallocated(x, 1);

 84:   if (!rctx) {
 85:     MPI_Comm comm;
 86:     PetscObjectGetComm((PetscObject)x, &comm);
 87:     PetscRandomCreate(comm, &randObj);
 88:     PetscRandomSetType(randObj, x->defaultrandtype);
 89:     PetscRandomSetFromOptions(randObj);
 90:     rctx = randObj;
 91:   }
 92:   PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0);
 93:   PetscUseTypeMethod(x, setrandom, rctx);
 94:   PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0);

 96:   MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY);
 97:   MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY);
 98:   PetscRandomDestroy(&randObj);
 99:   return 0;
100: }

102: /*@
103:    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in

105:    Logically Collective on mat

107:    Input Parameter:
108: .  mat - the factored matrix

110:    Output Parameters:
111: +  pivot - the pivot value computed
112: -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
113:          the share the matrix

115:    Level: advanced

117:    Notes:
118:     This routine does not work for factorizations done with external packages.

120:     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`

122:     This can be called on non-factored matrices that come from, for example, matrices used in SOR.

124: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
125:           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
126: @*/
127: PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
128: {
132:   *pivot = mat->factorerror_zeropivot_value;
133:   *row   = mat->factorerror_zeropivot_row;
134:   return 0;
135: }

137: /*@
138:    MatFactorGetError - gets the error code from a factorization

140:    Logically Collective on mat

142:    Input Parameters:
143: .  mat - the factored matrix

145:    Output Parameter:
146: .  err  - the error code

148:    Level: advanced

150:    Note:
151:     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.

153: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
154:           `MatFactorError`
155: @*/
156: PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
157: {
160:   *err = mat->factorerrortype;
161:   return 0;
162: }

164: /*@
165:    MatFactorClearError - clears the error code in a factorization

167:    Logically Collective on mat

169:    Input Parameter:
170: .  mat - the factored matrix

172:    Level: developer

174:    Note:
175:     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.

177: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
178:           `MatGetErrorCode()`, `MatFactorError`
179: @*/
180: PetscErrorCode MatFactorClearError(Mat mat)
181: {
183:   mat->factorerrortype             = MAT_FACTOR_NOERROR;
184:   mat->factorerror_zeropivot_value = 0.0;
185:   mat->factorerror_zeropivot_row   = 0;
186:   return 0;
187: }

189: PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
190: {
191:   Vec                r, l;
192:   const PetscScalar *al;
193:   PetscInt           i, nz, gnz, N, n;

195:   MatCreateVecs(mat, &r, &l);
196:   if (!cols) { /* nonzero rows */
197:     MatGetSize(mat, &N, NULL);
198:     MatGetLocalSize(mat, &n, NULL);
199:     VecSet(l, 0.0);
200:     VecSetRandom(r, NULL);
201:     MatMult(mat, r, l);
202:     VecGetArrayRead(l, &al);
203:   } else { /* nonzero columns */
204:     MatGetSize(mat, NULL, &N);
205:     MatGetLocalSize(mat, NULL, &n);
206:     VecSet(r, 0.0);
207:     VecSetRandom(l, NULL);
208:     MatMultTranspose(mat, l, r);
209:     VecGetArrayRead(r, &al);
210:   }
211:   if (tol <= 0.0) {
212:     for (i = 0, nz = 0; i < n; i++)
213:       if (al[i] != 0.0) nz++;
214:   } else {
215:     for (i = 0, nz = 0; i < n; i++)
216:       if (PetscAbsScalar(al[i]) > tol) nz++;
217:   }
218:   MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
219:   if (gnz != N) {
220:     PetscInt *nzr;
221:     PetscMalloc1(nz, &nzr);
222:     if (nz) {
223:       if (tol < 0) {
224:         for (i = 0, nz = 0; i < n; i++)
225:           if (al[i] != 0.0) nzr[nz++] = i;
226:       } else {
227:         for (i = 0, nz = 0; i < n; i++)
228:           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
229:       }
230:     }
231:     ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero);
232:   } else *nonzero = NULL;
233:   if (!cols) { /* nonzero rows */
234:     VecRestoreArrayRead(l, &al);
235:   } else {
236:     VecRestoreArrayRead(r, &al);
237:   }
238:   VecDestroy(&l);
239:   VecDestroy(&r);
240:   return 0;
241: }

243: /*@
244:       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix

246:   Input Parameter:
247: .    A  - the matrix

249:   Output Parameter:
250: .    keptrows - the rows that are not completely zero

252:   Note:
253:     keptrows is set to NULL if all rows are nonzero.

255:   Level: intermediate

257: .seealso: `Mat`, `MatFindZeroRows()`
258:  @*/
259: PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
260: {
266:   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
267:   else MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows);
268:   return 0;
269: }

271: /*@
272:       MatFindZeroRows - Locate all rows that are completely zero in the matrix

274:   Input Parameter:
275: .    A  - the matrix

277:   Output Parameter:
278: .    zerorows - the rows that are completely zero

280:   Note:
281:     zerorows is set to NULL if no rows are zero.

283:   Level: intermediate

285: .seealso: `Mat`, `MatFindNonzeroRows()`
286:  @*/
287: PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
288: {
289:   IS       keptrows;
290:   PetscInt m, n;

295:   MatFindNonzeroRows(mat, &keptrows);
296:   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
297:      In keeping with this convention, we set zerorows to NULL if there are no zero
298:      rows. */
299:   if (keptrows == NULL) {
300:     *zerorows = NULL;
301:   } else {
302:     MatGetOwnershipRange(mat, &m, &n);
303:     ISComplement(keptrows, m, n, zerorows);
304:     ISDestroy(&keptrows);
305:   }
306:   return 0;
307: }

309: /*@
310:    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling

312:    Not Collective

314:    Input Parameters:
315: .   A - the matrix

317:    Output Parameters:
318: .   a - the diagonal part (which is a SEQUENTIAL matrix)

320:    Notes:
321:    See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.

323:    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation.

325:    Level: advanced

327: .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
328: @*/
329: PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
330: {
335:   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
336:   else {
337:     PetscMPIInt size;

339:     MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);
341:     *a = A;
342:   }
343:   return 0;
344: }

346: /*@
347:    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.

349:    Collective on mat

351:    Input Parameters:
352: .  mat - the matrix

354:    Output Parameter:
355: .   trace - the sum of the diagonal entries

357:    Level: advanced

359: .seealso: `Mat`
360: @*/
361: PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
362: {
363:   Vec diag;

367:   MatCreateVecs(mat, &diag, NULL);
368:   MatGetDiagonal(mat, diag);
369:   VecSum(diag, trace);
370:   VecDestroy(&diag);
371:   return 0;
372: }

374: /*@
375:    MatRealPart - Zeros out the imaginary part of the matrix

377:    Logically Collective on mat

379:    Input Parameters:
380: .  mat - the matrix

382:    Level: advanced

384: .seealso: `MatImaginaryPart()`
385: @*/
386: PetscErrorCode MatRealPart(Mat mat)
387: {
392:   MatCheckPreallocated(mat, 1);
393:   PetscUseTypeMethod(mat, realpart);
394:   return 0;
395: }

397: /*@C
398:    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix

400:    Collective on mat

402:    Input Parameter:
403: .  mat - the matrix

405:    Output Parameters:
406: +   nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
407: -   ghosts - the global indices of the ghost points

409:    Note:
410:     the nghosts and ghosts are suitable to pass into `VecCreateGhost()`

412:    Level: advanced

414: .seealso: `Mat`, `VecCreateGhost()`
415: @*/
416: PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
417: {
422:   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
423:   else {
424:     if (nghosts) *nghosts = 0;
425:     if (ghosts) *ghosts = NULL;
426:   }
427:   return 0;
428: }

430: /*@
431:    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part

433:    Logically Collective on mat

435:    Input Parameters:
436: .  mat - the matrix

438:    Level: advanced

440: .seealso: `MatRealPart()`
441: @*/
442: PetscErrorCode MatImaginaryPart(Mat mat)
443: {
448:   MatCheckPreallocated(mat, 1);
449:   PetscUseTypeMethod(mat, imaginarypart);
450:   return 0;
451: }

453: /*@
454:    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)

456:    Not Collective

458:    Input Parameter:
459: .  mat - the matrix

461:    Output Parameters:
462: +  missing - is any diagonal missing
463: -  dd - first diagonal entry that is missing (optional) on this process

465:    Level: advanced

467: .seealso: `Mat`
468: @*/
469: PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
470: {
476:   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
477:   return 0;
478: }

480: /*@C
481:    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
482:    for each row that you get to ensure that your application does
483:    not bleed memory.

485:    Not Collective

487:    Input Parameters:
488: +  mat - the matrix
489: -  row - the row to get

491:    Output Parameters:
492: +  ncols -  if not NULL, the number of nonzeros in the row
493: .  cols - if not NULL, the column numbers
494: -  vals - if not NULL, the values

496:    Notes:
497:    This routine is provided for people who need to have direct access
498:    to the structure of a matrix.  We hope that we provide enough
499:    high-level matrix routines that few users will need it.

501:    `MatGetRow()` always returns 0-based column indices, regardless of
502:    whether the internal representation is 0-based (default) or 1-based.

504:    For better efficiency, set cols and/or vals to NULL if you do
505:    not wish to extract these quantities.

507:    The user can only examine the values extracted with `MatGetRow()`;
508:    the values cannot be altered.  To change the matrix entries, one
509:    must use `MatSetValues()`.

511:    You can only have one call to `MatGetRow()` outstanding for a particular
512:    matrix at a time, per processor. `MatGetRow()` can only obtain rows
513:    associated with the given processor, it cannot get rows from the
514:    other processors; for that we suggest using `MatCreateSubMatrices()`, then
515:    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
516:    is in the global number of rows.

518:    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.

520:    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.

522:    Fortran Note:
523:    The calling sequence from Fortran is
524: .vb
525:    MatGetRow(matrix,row,ncols,cols,values,ierr)
526:          Mat     matrix (input)
527:          integer row    (input)
528:          integer ncols  (output)
529:          integer cols(maxcols) (output)
530:          double precision (or double complex) values(maxcols) output
531: .ve
532:    where maxcols >= maximum nonzeros in any row of the matrix.

534:    Caution:
535:    Do not try to change the contents of the output arrays (cols and vals).
536:    In some cases, this may corrupt the matrix.

538:    Level: advanced

540: .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
541: @*/
542: PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
543: {
544:   PetscInt incols;

550:   MatCheckPreallocated(mat, 1);
552:   PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0);
553:   (*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
554:   if (ncols) *ncols = incols;
555:   PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0);
556:   return 0;
557: }

559: /*@
560:    MatConjugate - replaces the matrix values with their complex conjugates

562:    Logically Collective on mat

564:    Input Parameters:
565: .  mat - the matrix

567:    Level: advanced

569: .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
570: @*/
571: PetscErrorCode MatConjugate(Mat mat)
572: {
575:   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
576:     PetscUseTypeMethod(mat, conjugate);
577:     PetscObjectStateIncrease((PetscObject)mat);
578:   }
579:   return 0;
580: }

582: /*@C
583:    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.

585:    Not Collective

587:    Input Parameters:
588: +  mat - the matrix
589: .  row - the row to get
590: .  ncols, cols - the number of nonzeros and their columns
591: -  vals - if nonzero the column values

593:    Notes:
594:    This routine should be called after you have finished examining the entries.

596:    This routine zeros out ncols, cols, and vals. This is to prevent accidental
597:    us of the array after it has been restored. If you pass NULL, it will
598:    not zero the pointers.  Use of cols or vals after `MatRestoreRow()` is invalid.

600:    Fortran Notes:
601:    The calling sequence from Fortran is
602: .vb
603:    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
604:       Mat     matrix (input)
605:       integer row    (input)
606:       integer ncols  (output)
607:       integer cols(maxcols) (output)
608:       double precision (or double complex) values(maxcols) output
609: .ve
610:    Where maxcols >= maximum nonzeros in any row of the matrix.

612:    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
613:    before another call to `MatGetRow()` can be made.

615:    Level: advanced

617: .seealso: `MatGetRow()`
618: @*/
619: PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
620: {
624:   if (!mat->ops->restorerow) return 0;
625:   (*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
626:   if (ncols) *ncols = 0;
627:   if (cols) *cols = NULL;
628:   if (vals) *vals = NULL;
629:   return 0;
630: }

632: /*@
633:    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
634:    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.

636:    Not Collective

638:    Input Parameters:
639: .  mat - the matrix

641:    Note:
642:    The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.

644:    Level: advanced

646: .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
647: @*/
648: PetscErrorCode MatGetRowUpperTriangular(Mat mat)
649: {
654:   MatCheckPreallocated(mat, 1);
655:   if (!mat->ops->getrowuppertriangular) return 0;
656:   PetscUseTypeMethod(mat, getrowuppertriangular);
657:   return 0;
658: }

660: /*@
661:    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.

663:    Not Collective

665:    Input Parameters:
666: .  mat - the matrix

668:    Note:
669:    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.

671:    Level: advanced

673: .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()`
674: @*/
675: PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
676: {
681:   MatCheckPreallocated(mat, 1);
682:   if (!mat->ops->restorerowuppertriangular) return 0;
683:   PetscUseTypeMethod(mat, restorerowuppertriangular);
684:   return 0;
685: }

687: /*@C
688:    MatSetOptionsPrefix - Sets the prefix used for searching for all
689:    `Mat` options in the database.

691:    Logically Collective on A

693:    Input Parameters:
694: +  A - the matrix
695: -  prefix - the prefix to prepend to all option names

697:    Notes:
698:    A hyphen (-) must NOT be given at the beginning of the prefix name.
699:    The first character of all runtime options is AUTOMATICALLY the hyphen.

701:    This is NOT used for options for the factorization of the matrix. Normally the
702:    prefix is automatically passed in from the PC calling the factorization. To set
703:    it directly use  `MatSetOptionsPrefixFactor()`

705:    Level: advanced

707: .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
708: @*/
709: PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
710: {
712:   PetscObjectSetOptionsPrefix((PetscObject)A, prefix);
713:   return 0;
714: }

716: /*@C
717:    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
718:    for matrices created with `MatGetFactor()`

720:    Logically Collective on A

722:    Input Parameters:
723: +  A - the matrix
724: -  prefix - the prefix to prepend to all option names for the factored matrix

726:    Notes:
727:    A hyphen (-) must NOT be given at the beginning of the prefix name.
728:    The first character of all runtime options is AUTOMATICALLY the hyphen.

730:    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
731:    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`

733:    Level: developer

735: .seealso:   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
736: @*/
737: PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
738: {
740:   if (prefix) {
743:     if (prefix != A->factorprefix) {
744:       PetscFree(A->factorprefix);
745:       PetscStrallocpy(prefix, &A->factorprefix);
746:     }
747:   } else PetscFree(A->factorprefix);
748:   return 0;
749: }

751: /*@C
752:    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
753:    for matrices created with `MatGetFactor()`

755:    Logically Collective on A

757:    Input Parameters:
758: +  A - the matrix
759: -  prefix - the prefix to prepend to all option names for the factored matrix

761:    Notes:
762:    A hyphen (-) must NOT be given at the beginning of the prefix name.
763:    The first character of all runtime options is AUTOMATICALLY the hyphen.

765:    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
766:    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`

768:    Level: developer

770: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
771:           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
772:           `MatSetOptionsPrefix()`
773: @*/
774: PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
775: {
776:   char  *buf = A->factorprefix;
777:   size_t len1, len2;

780:   if (!prefix) return 0;
781:   if (!buf) {
782:     MatSetOptionsPrefixFactor(A, prefix);
783:     return 0;
784:   }

787:   PetscStrlen(prefix, &len1);
788:   PetscStrlen(buf, &len2);
789:   PetscMalloc1(1 + len1 + len2, &A->factorprefix);
790:   PetscStrcpy(A->factorprefix, buf);
791:   PetscStrcat(A->factorprefix, prefix);
792:   PetscFree(buf);
793:   return 0;
794: }

796: /*@C
797:    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
798:    matrix options in the database.

800:    Logically Collective on A

802:    Input Parameters:
803: +  A - the matrix
804: -  prefix - the prefix to prepend to all option names

806:    Note:
807:    A hyphen (-) must NOT be given at the beginning of the prefix name.
808:    The first character of all runtime options is AUTOMATICALLY the hyphen.

810:    Level: advanced

812: .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
813: @*/
814: PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
815: {
817:   PetscObjectAppendOptionsPrefix((PetscObject)A, prefix);
818:   return 0;
819: }

821: /*@C
822:    MatGetOptionsPrefix - Gets the prefix used for searching for all
823:    matrix options in the database.

825:    Not Collective

827:    Input Parameter:
828: .  A - the matrix

830:    Output Parameter:
831: .  prefix - pointer to the prefix string used

833:    Fortran Note:
834:     On the fortran side, the user should pass in a string 'prefix' of
835:    sufficient length to hold the prefix.

837:    Level: advanced

839: .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
840: @*/
841: PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
842: {
845:   PetscObjectGetOptionsPrefix((PetscObject)A, prefix);
846:   return 0;
847: }

849: /*@
850:    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.

852:    Collective on A

854:    Input Parameters:
855: .  A - the matrix

857:    Notes:
858:    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.

860:    Users can reset the preallocation to access the original memory.

862:    Currently only supported for  `MATMPIAIJ` and `MATSEQAIJ` matrices.

864:    Level: beginner

866: .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
867: @*/
868: PetscErrorCode MatResetPreallocation(Mat A)
869: {
872:   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
873:   return 0;
874: }

876: /*@
877:    MatSetUp - Sets up the internal matrix data structures for later use.

879:    Collective on A

881:    Input Parameters:
882: .  A - the matrix

884:    Notes:
885:    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.

887:    If a suitable preallocation routine is used, this function does not need to be called.

889:    See the Performance chapter of the PETSc users manual for how to preallocate matrices

891:    This routine is called internally by other matrix functions when needed so rarely needs to be called by users

893:    Level: intermediate

895: .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
896: @*/
897: PetscErrorCode MatSetUp(Mat A)
898: {
900:   if (!((PetscObject)A)->type_name) {
901:     PetscMPIInt size;

903:     MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);
904:     MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ);
905:   }
906:   if (!A->preallocated && A->ops->setup) {
907:     PetscInfo(A, "Warning not preallocating matrix storage\n");
908:     PetscUseTypeMethod(A, setup);
909:   }
910:   PetscLayoutSetUp(A->rmap);
911:   PetscLayoutSetUp(A->cmap);
912:   A->preallocated = PETSC_TRUE;
913:   return 0;
914: }

916: #if defined(PETSC_HAVE_SAWS)
917: #include <petscviewersaws.h>
918: #endif

920: /*@C
921:    MatViewFromOptions - View properties of the matrix from the options database

923:    Collective on A

925:    Input Parameters:
926: +  A - the matrix
927: .  obj - optional additional object that provides the options prefix to use
928: -  name - command line option

930:   Options Database:
931: .  -mat_view [viewertype]:... - the viewer and its options

933:   Notes:
934: .vb
935:     If no value is provided ascii:stdout is used
936:        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
937:                                                   for example ascii::ascii_info prints just the information about the object not all details
938:                                                   unless :append is given filename opens in write mode, overwriting what was already there
939:        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
940:        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
941:        socket[:port]                             defaults to the standard output port
942:        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
943: .ve

945:    Level: intermediate

947: .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
948: @*/
949: PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
950: {
952:   PetscObjectViewFromOptions((PetscObject)A, obj, name);
953:   return 0;
954: }

956: /*@C
957:    MatView - display information about a matrix in a variety ways

959:    Collective on mat

961:    Input Parameters:
962: +  mat - the matrix
963: -  viewer - visualization context

965:   Notes:
966:   The available visualization contexts include
967: +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
968: .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
969: .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
970: -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure

972:    The user can open alternative visualization contexts with
973: +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
974: .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
975:          specified file; corresponding input uses MatLoad()
976: .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
977:          an X window display
978: -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
979:          Currently only the sequential dense and AIJ
980:          matrix types support the Socket viewer.

982:    The user can call `PetscViewerPushFormat()` to specify the output
983:    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
984:    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
985: +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
986: .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
987: .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
988: .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
989:          format common among all matrix types
990: .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
991:          format (which is in many cases the same as the default)
992: .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
993:          size and structure (not the matrix entries)
994: -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
995:          the matrix structure

997:    Options Database Keys:
998: +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
999: .  -mat_view ::ascii_info_detail - Prints more detailed info
1000: .  -mat_view - Prints matrix in ASCII format
1001: .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1002: .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1003: .  -display <name> - Sets display name (default is host)
1004: .  -draw_pause <sec> - Sets number of seconds to pause after display
1005: .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1006: .  -viewer_socket_machine <machine> -
1007: .  -viewer_socket_port <port> -
1008: .  -mat_view binary - save matrix to file in binary format
1009: -  -viewer_binary_filename <name> -

1011:    Level: beginner

1013:    Notes:
1014:     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1015:     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.

1017:     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).

1019:     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1020:       viewer is used.

1022:       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1023:       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.

1025:       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1026:       and then use the following mouse functions.
1027: .vb
1028:   left mouse: zoom in
1029:   middle mouse: zoom out
1030:   right mouse: continue with the simulation
1031: .ve

1033: .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`,
1034:           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1035: @*/
1036: PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1037: {
1038:   PetscInt          rows, cols, rbs, cbs;
1039:   PetscBool         isascii, isstring, issaws;
1040:   PetscViewerFormat format;
1041:   PetscMPIInt       size;

1045:   if (!viewer) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer);
1048:   MatCheckPreallocated(mat, 1);

1050:   PetscViewerGetFormat(viewer, &format);
1051:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
1052:   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) return 0;

1054:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring);
1055:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
1056:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws);

1059:   PetscLogEventBegin(MAT_View, mat, viewer, 0, 0);
1060:   if (isascii) {
1062:     PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer);
1063:     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1064:       MatNullSpace nullsp, transnullsp;

1066:       PetscViewerASCIIPushTab(viewer);
1067:       MatGetSize(mat, &rows, &cols);
1068:       MatGetBlockSizes(mat, &rbs, &cbs);
1069:       if (rbs != 1 || cbs != 1) {
1070:         if (rbs != cbs) PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs);
1071:         else PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs);
1072:       } else PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols);
1073:       if (mat->factortype) {
1074:         MatSolverType solver;
1075:         MatFactorGetSolverType(mat, &solver);
1076:         PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver);
1077:       }
1078:       if (mat->ops->getinfo) {
1079:         MatInfo info;
1080:         MatGetInfo(mat, MAT_GLOBAL_SUM, &info);
1081:         PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated);
1082:         if (!mat->factortype) PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs);
1083:       }
1084:       MatGetNullSpace(mat, &nullsp);
1085:       MatGetTransposeNullSpace(mat, &transnullsp);
1086:       if (nullsp) PetscViewerASCIIPrintf(viewer, "  has attached null space\n");
1087:       if (transnullsp && transnullsp != nullsp) PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n");
1088:       MatGetNearNullSpace(mat, &nullsp);
1089:       if (nullsp) PetscViewerASCIIPrintf(viewer, "  has attached near null space\n");
1090:       PetscViewerASCIIPushTab(viewer);
1091:       MatProductView(mat, viewer);
1092:       PetscViewerASCIIPopTab(viewer);
1093:     }
1094:   } else if (issaws) {
1095: #if defined(PETSC_HAVE_SAWS)
1096:     PetscMPIInt rank;

1098:     PetscObjectName((PetscObject)mat);
1099:     MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1100:     if (!((PetscObject)mat)->amsmem && rank == 0) PetscObjectViewSAWs((PetscObject)mat, viewer);
1101: #endif
1102:   } else if (isstring) {
1103:     const char *type;
1104:     MatGetType(mat, &type);
1105:     PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type);
1106:     PetscTryTypeMethod(mat, view, viewer);
1107:   }
1108:   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1109:     PetscViewerASCIIPushTab(viewer);
1110:     PetscUseTypeMethod(mat, viewnative, viewer);
1111:     PetscViewerASCIIPopTab(viewer);
1112:   } else if (mat->ops->view) {
1113:     PetscViewerASCIIPushTab(viewer);
1114:     PetscUseTypeMethod(mat, view, viewer);
1115:     PetscViewerASCIIPopTab(viewer);
1116:   }
1117:   if (isascii) {
1118:     PetscViewerGetFormat(viewer, &format);
1119:     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscViewerASCIIPopTab(viewer);
1120:   }
1121:   PetscLogEventEnd(MAT_View, mat, viewer, 0, 0);
1122:   return 0;
1123: }

1125: #if defined(PETSC_USE_DEBUG)
1126: #include <../src/sys/totalview/tv_data_display.h>
1127: PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1128: {
1129:   TV_add_row("Local rows", "int", &mat->rmap->n);
1130:   TV_add_row("Local columns", "int", &mat->cmap->n);
1131:   TV_add_row("Global rows", "int", &mat->rmap->N);
1132:   TV_add_row("Global columns", "int", &mat->cmap->N);
1133:   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1134:   return TV_format_OK;
1135: }
1136: #endif

1138: /*@C
1139:    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1140:    with `MatView()`.  The matrix format is determined from the options database.
1141:    Generates a parallel MPI matrix if the communicator has more than one
1142:    processor.  The default matrix type is `MATAIJ`.

1144:    Collective on mat

1146:    Input Parameters:
1147: +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1148:             or some related function before a call to `MatLoad()`
1149: -  viewer - binary/HDF5 file viewer

1151:    Options Database Keys:
1152:    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1153:    block size
1154: .    -matload_block_size <bs> - set block size

1156:    Level: beginner

1158:    Notes:
1159:    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1160:    `Mat` before calling this routine if you wish to set it from the options database.

1162:    `MatLoad()` automatically loads into the options database any options
1163:    given in the file filename.info where filename is the name of the file
1164:    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1165:    file will be ignored if you use the -viewer_binary_skip_info option.

1167:    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1168:    sets the default matrix type AIJ and sets the local and global sizes.
1169:    If type and/or size is already set, then the same are used.

1171:    In parallel, each processor can load a subset of rows (or the
1172:    entire matrix).  This routine is especially useful when a large
1173:    matrix is stored on disk and only part of it is desired on each
1174:    processor.  For example, a parallel solver may access only some of
1175:    the rows from each processor.  The algorithm used here reads
1176:    relatively small blocks of data rather than reading the entire
1177:    matrix and then subsetting it.

1179:    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1180:    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1181:    or the sequence like
1182: .vb
1183:     `PetscViewer` v;
1184:     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1185:     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1186:     `PetscViewerSetFromOptions`(v);
1187:     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1188:     `PetscViewerFileSetName`(v,"datafile");
1189: .ve
1190:    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1191: $ -viewer_type {binary,hdf5}

1193:    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1194:    and src/mat/tutorials/ex10.c with the second approach.

1196:    Notes about the PETSc binary format:
1197:    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1198:    is read onto rank 0 and then shipped to its destination rank, one after another.
1199:    Multiple objects, both matrices and vectors, can be stored within the same file.
1200:    Their PetscObject name is ignored; they are loaded in the order of their storage.

1202:    Most users should not need to know the details of the binary storage
1203:    format, since `MatLoad()` and `MatView()` completely hide these details.
1204:    But for anyone who's interested, the standard binary matrix storage
1205:    format is

1207: $    PetscInt    MAT_FILE_CLASSID
1208: $    PetscInt    number of rows
1209: $    PetscInt    number of columns
1210: $    PetscInt    total number of nonzeros
1211: $    PetscInt    *number nonzeros in each row
1212: $    PetscInt    *column indices of all nonzeros (starting index is zero)
1213: $    PetscScalar *values of all nonzeros

1215:    PETSc automatically does the byte swapping for
1216: machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1217: Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1218: read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1219: and `PetscBinaryWrite()` to see how this may be done.

1221:    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1222:    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1223:    Each processor's chunk is loaded independently by its owning rank.
1224:    Multiple objects, both matrices and vectors, can be stored within the same file.
1225:    They are looked up by their PetscObject name.

1227:    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1228:    by default the same structure and naming of the AIJ arrays and column count
1229:    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1230: $    save example.mat A b -v7.3
1231:    can be directly read by this routine (see Reference 1 for details).
1232:    Note that depending on your MATLAB version, this format might be a default,
1233:    otherwise you can set it as default in Preferences.

1235:    Unless -nocompression flag is used to save the file in MATLAB,
1236:    PETSc must be configured with ZLIB package.

1238:    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c

1240:    Current HDF5 (MAT-File) limitations:
1241:    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.

1243:    Corresponding `MatView()` is not yet implemented.

1245:    The loaded matrix is actually a transpose of the original one in MATLAB,
1246:    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1247:    With this format, matrix is automatically transposed by PETSc,
1248:    unless the matrix is marked as SPD or symmetric
1249:    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).

1251:    References:
1252: .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version

1254: .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1255:  @*/
1256: PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1257: {
1258:   PetscBool flg;


1263:   if (!((PetscObject)mat)->type_name) MatSetType(mat, MATAIJ);

1265:   flg = PETSC_FALSE;
1266:   PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL);
1267:   if (flg) {
1268:     MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE);
1269:     MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE);
1270:   }
1271:   flg = PETSC_FALSE;
1272:   PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL);
1273:   if (flg) MatSetOption(mat, MAT_SPD, PETSC_TRUE);

1275:   PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0);
1276:   PetscUseTypeMethod(mat, load, viewer);
1277:   PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0);
1278:   return 0;
1279: }

1281: static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1282: {
1283:   Mat_Redundant *redund = *redundant;

1285:   if (redund) {
1286:     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1287:       ISDestroy(&redund->isrow);
1288:       ISDestroy(&redund->iscol);
1289:       MatDestroySubMatrices(1, &redund->matseq);
1290:     } else {
1291:       PetscFree2(redund->send_rank, redund->recv_rank);
1292:       PetscFree(redund->sbuf_j);
1293:       PetscFree(redund->sbuf_a);
1294:       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1295:         PetscFree(redund->rbuf_j[i]);
1296:         PetscFree(redund->rbuf_a[i]);
1297:       }
1298:       PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a);
1299:     }

1301:     if (redund->subcomm) PetscCommDestroy(&redund->subcomm);
1302:     PetscFree(redund);
1303:   }
1304:   return 0;
1305: }

1307: /*@C
1308:    MatDestroy - Frees space taken by a matrix.

1310:    Collective on A

1312:    Input Parameter:
1313: .  A - the matrix

1315:    Level: beginner

1317:    Developer Note:
1318:    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1319:    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1320:    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1321:    if changes are needed here.

1323: .seealso: `Mat`, `MatCreate()`
1324: @*/
1325: PetscErrorCode MatDestroy(Mat *A)
1326: {
1327:   if (!*A) return 0;
1329:   if (--((PetscObject)(*A))->refct > 0) {
1330:     *A = NULL;
1331:     return 0;
1332:   }

1334:   /* if memory was published with SAWs then destroy it */
1335:   PetscObjectSAWsViewOff((PetscObject)*A);
1336:   PetscTryTypeMethod((*A), destroy);

1338:   PetscFree((*A)->factorprefix);
1339:   PetscFree((*A)->defaultvectype);
1340:   PetscFree((*A)->defaultrandtype);
1341:   PetscFree((*A)->bsizes);
1342:   PetscFree((*A)->solvertype);
1343:   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscFree((*A)->preferredordering[i]);
1344:   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1345:   MatDestroy_Redundant(&(*A)->redundant);
1346:   MatProductClear(*A);
1347:   MatNullSpaceDestroy(&(*A)->nullsp);
1348:   MatNullSpaceDestroy(&(*A)->transnullsp);
1349:   MatNullSpaceDestroy(&(*A)->nearnullsp);
1350:   MatDestroy(&(*A)->schur);
1351:   PetscLayoutDestroy(&(*A)->rmap);
1352:   PetscLayoutDestroy(&(*A)->cmap);
1353:   PetscHeaderDestroy(A);
1354:   return 0;
1355: }

1357: /*@C
1358:    MatSetValues - Inserts or adds a block of values into a matrix.
1359:    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1360:    MUST be called after all calls to `MatSetValues()` have been completed.

1362:    Not Collective

1364:    Input Parameters:
1365: +  mat - the matrix
1366: .  v - a logically two-dimensional array of values
1367: .  m, idxm - the number of rows and their global indices
1368: .  n, idxn - the number of columns and their global indices
1369: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

1371:    Notes:
1372:    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1373:       `MatSetUp()` before using this routine

1375:    By default the values, v, are row-oriented. See `MatSetOption()` for other options.

1377:    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1378:    options cannot be mixed without intervening calls to the assembly
1379:    routines.

1381:    `MatSetValues()` uses 0-based row and column numbers in Fortran
1382:    as well as in C.

1384:    Negative indices may be passed in idxm and idxn, these rows and columns are
1385:    simply ignored. This allows easily inserting element stiffness matrices
1386:    with homogeneous Dirchlet boundary conditions that you don't want represented
1387:    in the matrix.

1389:    Efficiency Alert:
1390:    The routine `MatSetValuesBlocked()` may offer much better efficiency
1391:    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).

1393:    Level: beginner

1395:    Developer Note:
1396:    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1397:    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.

1399: .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1400:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1401: @*/
1402: PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1403: {
1407:   if (!m || !n) return 0; /* no values to insert */
1410:   MatCheckPreallocated(mat, 1);

1412:   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;

1415:   if (PetscDefined(USE_DEBUG)) {
1416:     PetscInt i, j;

1419:     for (i = 0; i < m; i++) {
1420:       for (j = 0; j < n; j++) {
1421:         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1422: #if defined(PETSC_USE_COMPLEX)
1423:           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1424: #else
1425:           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1426: #endif
1427:       }
1428:     }
1431:   }

1433:   if (mat->assembled) {
1434:     mat->was_assembled = PETSC_TRUE;
1435:     mat->assembled     = PETSC_FALSE;
1436:   }
1437:   PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1438:   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1439:   PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1440:   return 0;
1441: }

1443: /*@C
1444:    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1445:    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1446:    MUST be called after all calls to `MatSetValues()` have been completed.

1448:    Not Collective

1450:    Input Parameters:
1451: +  mat - the matrix
1452: .  v - a logically two-dimensional array of values
1453: .  ism - the rows to provide
1454: .  isn - the columns to provide
1455: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

1457:    Notes:
1458:    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1459:       `MatSetUp()` before using this routine

1461:    By default the values, v, are row-oriented. See `MatSetOption()` for other options.

1463:    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1464:    options cannot be mixed without intervening calls to the assembly
1465:    routines.

1467:    MatSetValues() uses 0-based row and column numbers in Fortran
1468:    as well as in C.

1470:    Negative indices may be passed in ism and isn, these rows and columns are
1471:    simply ignored. This allows easily inserting element stiffness matrices
1472:    with homogeneous Dirchlet boundary conditions that you don't want represented
1473:    in the matrix.

1475:    Efficiency Alert:
1476:    The routine `MatSetValuesBlocked()` may offer much better efficiency
1477:    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).

1479:    Level: beginner

1481:    Developer Notes:
1482:     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1483:                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.

1485:     This is currently not optimized for any particular `ISType`

1487: .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1488:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1489: @*/
1490: PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1491: {
1492:   PetscInt        m, n;
1493:   const PetscInt *rows, *cols;

1497:   ISGetIndices(ism, &rows);
1498:   ISGetIndices(isn, &cols);
1499:   ISGetLocalSize(ism, &m);
1500:   ISGetLocalSize(isn, &n);
1501:   MatSetValues(mat, m, rows, n, cols, v, addv);
1502:   ISRestoreIndices(ism, &rows);
1503:   ISRestoreIndices(isn, &cols);
1504:   return 0;
1505: }

1507: /*@
1508:    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1509:         values into a matrix

1511:    Not Collective

1513:    Input Parameters:
1514: +  mat - the matrix
1515: .  row - the (block) row to set
1516: -  v - a logically two-dimensional array of values

1518:    Notes:
1519:    By the values, v, are column-oriented (for the block version) and sorted

1521:    All the nonzeros in the row must be provided

1523:    The matrix must have previously had its column indices set

1525:    The row must belong to this process

1527:    Level: intermediate

1529: .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1530:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1531: @*/
1532: PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1533: {
1534:   PetscInt globalrow;

1539:   ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow);
1540:   MatSetValuesRow(mat, globalrow, v);
1541:   return 0;
1542: }

1544: /*@
1545:    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1546:         values into a matrix

1548:    Not Collective

1550:    Input Parameters:
1551: +  mat - the matrix
1552: .  row - the (block) row to set
1553: -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values

1555:    Notes:
1556:    The values, v, are column-oriented for the block version.

1558:    All the nonzeros in the row must be provided

1560:    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.

1562:    The row must belong to this process

1564:    Level: advanced

1566: .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1567:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1568: @*/
1569: PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1570: {
1574:   MatCheckPreallocated(mat, 1);
1578:   mat->insertmode = INSERT_VALUES;

1580:   if (mat->assembled) {
1581:     mat->was_assembled = PETSC_TRUE;
1582:     mat->assembled     = PETSC_FALSE;
1583:   }
1584:   PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1585:   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1586:   PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1587:   return 0;
1588: }

1590: /*@
1591:    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1592:      Using structured grid indexing

1594:    Not Collective

1596:    Input Parameters:
1597: +  mat - the matrix
1598: .  m - number of rows being entered
1599: .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1600: .  n - number of columns being entered
1601: .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1602: .  v - a logically two-dimensional array of values
1603: -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values

1605:    Notes:
1606:    By default the values, v, are row-oriented.  See `MatSetOption()` for other options.

1608:    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1609:    options cannot be mixed without intervening calls to the assembly
1610:    routines.

1612:    The grid coordinates are across the entire grid, not just the local portion

1614:    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1615:    as well as in C.

1617:    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine

1619:    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1620:    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.

1622:    The columns and rows in the stencil passed in MUST be contained within the
1623:    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1624:    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1625:    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1626:    first i index you can use in your column and row indices in `MatSetStencil()` is 5.

1628:    In Fortran idxm and idxn should be declared as
1629: $     MatStencil idxm(4,m),idxn(4,n)
1630:    and the values inserted using
1631: $    idxm(MatStencil_i,1) = i
1632: $    idxm(MatStencil_j,1) = j
1633: $    idxm(MatStencil_k,1) = k
1634: $    idxm(MatStencil_c,1) = c
1635:    etc

1637:    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1638:    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1639:    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1640:    `DM_BOUNDARY_PERIODIC` boundary type.

1642:    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1643:    a single value per point) you can skip filling those indices.

1645:    Inspired by the structured grid interface to the HYPRE package
1646:    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)

1648:    Efficiency Alert:
1649:    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1650:    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).

1652:    Level: beginner

1654: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1655:           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1656: @*/
1657: PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1658: {
1659:   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1660:   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1661:   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);

1663:   if (!m || !n) return 0; /* no values to insert */

1669:   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1670:     jdxm = buf;
1671:     jdxn = buf + m;
1672:   } else {
1673:     PetscMalloc2(m, &bufm, n, &bufn);
1674:     jdxm = bufm;
1675:     jdxn = bufn;
1676:   }
1677:   for (i = 0; i < m; i++) {
1678:     for (j = 0; j < 3 - sdim; j++) dxm++;
1679:     tmp = *dxm++ - starts[0];
1680:     for (j = 0; j < dim - 1; j++) {
1681:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1682:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1683:     }
1684:     if (mat->stencil.noc) dxm++;
1685:     jdxm[i] = tmp;
1686:   }
1687:   for (i = 0; i < n; i++) {
1688:     for (j = 0; j < 3 - sdim; j++) dxn++;
1689:     tmp = *dxn++ - starts[0];
1690:     for (j = 0; j < dim - 1; j++) {
1691:       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1692:       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1693:     }
1694:     if (mat->stencil.noc) dxn++;
1695:     jdxn[i] = tmp;
1696:   }
1697:   MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv);
1698:   PetscFree2(bufm, bufn);
1699:   return 0;
1700: }

1702: /*@
1703:    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1704:      Using structured grid indexing

1706:    Not Collective

1708:    Input Parameters:
1709: +  mat - the matrix
1710: .  m - number of rows being entered
1711: .  idxm - grid coordinates for matrix rows being entered
1712: .  n - number of columns being entered
1713: .  idxn - grid coordinates for matrix columns being entered
1714: .  v - a logically two-dimensional array of values
1715: -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values

1717:    Notes:
1718:    By default the values, v, are row-oriented and unsorted.
1719:    See `MatSetOption()` for other options.

1721:    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1722:    options cannot be mixed without intervening calls to the assembly
1723:    routines.

1725:    The grid coordinates are across the entire grid, not just the local portion

1727:    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1728:    as well as in C.

1730:    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine

1732:    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1733:    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.

1735:    The columns and rows in the stencil passed in MUST be contained within the
1736:    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1737:    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1738:    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1739:    first i index you can use in your column and row indices in `MatSetStencil()` is 5.

1741:    In Fortran idxm and idxn should be declared as
1742: $     MatStencil idxm(4,m),idxn(4,n)
1743:    and the values inserted using
1744: $    idxm(MatStencil_i,1) = i
1745: $    idxm(MatStencil_j,1) = j
1746: $    idxm(MatStencil_k,1) = k
1747:    etc

1749:    Negative indices may be passed in idxm and idxn, these rows and columns are
1750:    simply ignored. This allows easily inserting element stiffness matrices
1751:    with homogeneous Dirchlet boundary conditions that you don't want represented
1752:    in the matrix.

1754:    Inspired by the structured grid interface to the HYPRE package
1755:    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)

1757:    Level: beginner

1759: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1760:           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1761:           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1762: @*/
1763: PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1764: {
1765:   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1766:   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1767:   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);

1769:   if (!m || !n) return 0; /* no values to insert */

1776:   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1777:     jdxm = buf;
1778:     jdxn = buf + m;
1779:   } else {
1780:     PetscMalloc2(m, &bufm, n, &bufn);
1781:     jdxm = bufm;
1782:     jdxn = bufn;
1783:   }
1784:   for (i = 0; i < m; i++) {
1785:     for (j = 0; j < 3 - sdim; j++) dxm++;
1786:     tmp = *dxm++ - starts[0];
1787:     for (j = 0; j < sdim - 1; j++) {
1788:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1789:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1790:     }
1791:     dxm++;
1792:     jdxm[i] = tmp;
1793:   }
1794:   for (i = 0; i < n; i++) {
1795:     for (j = 0; j < 3 - sdim; j++) dxn++;
1796:     tmp = *dxn++ - starts[0];
1797:     for (j = 0; j < sdim - 1; j++) {
1798:       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1799:       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1800:     }
1801:     dxn++;
1802:     jdxn[i] = tmp;
1803:   }
1804:   MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv);
1805:   PetscFree2(bufm, bufn);
1806:   return 0;
1807: }

1809: /*@
1810:    MatSetStencil - Sets the grid information for setting values into a matrix via
1811:         `MatSetValuesStencil()`

1813:    Not Collective

1815:    Input Parameters:
1816: +  mat - the matrix
1817: .  dim - dimension of the grid 1, 2, or 3
1818: .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1819: .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1820: -  dof - number of degrees of freedom per node

1822:    Notes:
1823:    Inspired by the structured grid interface to the HYPRE package
1824:    (www.llnl.gov/CASC/hyper)

1826:    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1827:    user.

1829:    Level: beginner

1831: .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1832:           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1833: @*/
1834: PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1835: {

1840:   mat->stencil.dim = dim + (dof > 1);
1841:   for (PetscInt i = 0; i < dim; i++) {
1842:     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1843:     mat->stencil.starts[i] = starts[dim - i - 1];
1844:   }
1845:   mat->stencil.dims[dim]   = dof;
1846:   mat->stencil.starts[dim] = 0;
1847:   mat->stencil.noc         = (PetscBool)(dof == 1);
1848:   return 0;
1849: }

1851: /*@C
1852:    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.

1854:    Not Collective

1856:    Input Parameters:
1857: +  mat - the matrix
1858: .  v - a logically two-dimensional array of values
1859: .  m, idxm - the number of block rows and their global block indices
1860: .  n, idxn - the number of block columns and their global block indices
1861: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values

1863:    Notes:
1864:    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1865:    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.

1867:    The m and n count the NUMBER of blocks in the row direction and column direction,
1868:    NOT the total number of rows/columns; for example, if the block size is 2 and
1869:    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1870:    The values in idxm would be 1 2; that is the first index for each block divided by
1871:    the block size.

1873:    Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1874:    preallocating it).

1876:    By default the values, v, are row-oriented, so the layout of
1877:    v is the same as for `MatSetValues()`. See `MatSetOption()` for other options.

1879:    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1880:    options cannot be mixed without intervening calls to the assembly
1881:    routines.

1883:    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1884:    as well as in C.

1886:    Negative indices may be passed in idxm and idxn, these rows and columns are
1887:    simply ignored. This allows easily inserting element stiffness matrices
1888:    with homogeneous Dirchlet boundary conditions that you don't want represented
1889:    in the matrix.

1891:    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1892:    internal searching must be done to determine where to place the
1893:    data in the matrix storage space.  By instead inserting blocks of
1894:    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1895:    reduced.

1897:    Example:
1898: $   Suppose m=n=2 and block size(bs) = 2 The array is
1899: $
1900: $   1  2  | 3  4
1901: $   5  6  | 7  8
1902: $   - - - | - - -
1903: $   9  10 | 11 12
1904: $   13 14 | 15 16
1905: $
1906: $   v[] should be passed in like
1907: $   v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1908: $
1909: $  If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1910: $   v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]

1912:    Level: intermediate

1914: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1915: @*/
1916: PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1917: {
1921:   if (!m || !n) return 0; /* no values to insert */
1924:   MatCheckPreallocated(mat, 1);
1925:   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1927:   if (PetscDefined(USE_DEBUG)) {
1930:   }
1931:   if (PetscDefined(USE_DEBUG)) {
1932:     PetscInt rbs, cbs, M, N, i;
1933:     MatGetBlockSizes(mat, &rbs, &cbs);
1934:     MatGetSize(mat, &M, &N);
1937:   }
1938:   if (mat->assembled) {
1939:     mat->was_assembled = PETSC_TRUE;
1940:     mat->assembled     = PETSC_FALSE;
1941:   }
1942:   PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1943:   if (mat->ops->setvaluesblocked) {
1944:     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1945:   } else {
1946:     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1947:     PetscInt i, j, bs, cbs;

1949:     MatGetBlockSizes(mat, &bs, &cbs);
1950:     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1951:       iidxm = buf;
1952:       iidxn = buf + m * bs;
1953:     } else {
1954:       PetscMalloc2(m * bs, &bufr, n * cbs, &bufc);
1955:       iidxm = bufr;
1956:       iidxn = bufc;
1957:     }
1958:     for (i = 0; i < m; i++) {
1959:       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
1960:     }
1961:     if (m != n || bs != cbs || idxm != idxn) {
1962:       for (i = 0; i < n; i++) {
1963:         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
1964:       }
1965:     } else iidxn = iidxm;
1966:     MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv);
1967:     PetscFree2(bufr, bufc);
1968:   }
1969:   PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1970:   return 0;
1971: }

1973: /*@C
1974:    MatGetValues - Gets a block of local values from a matrix.

1976:    Not Collective; can only return values that are owned by the give process

1978:    Input Parameters:
1979: +  mat - the matrix
1980: .  v - a logically two-dimensional array for storing the values
1981: .  m, idxm - the number of rows and their global indices
1982: -  n, idxn - the number of columns and their global indices

1984:    Notes:
1985:      The user must allocate space (m*n `PetscScalar`s) for the values, v.
1986:      The values, v, are then returned in a row-oriented format,
1987:      analogous to that used by default in `MatSetValues()`.

1989:      `MatGetValues()` uses 0-based row and column numbers in
1990:      Fortran as well as in C.

1992:      `MatGetValues()` requires that the matrix has been assembled
1993:      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
1994:      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
1995:      without intermediate matrix assembly.

1997:      Negative row or column indices will be ignored and those locations in v[] will be
1998:      left unchanged.

2000:      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2001:      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2002:      from `MatGetOwnershipRange`(mat,&rstart,&rend).

2004:    Level: advanced

2006: .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2007: @*/
2008: PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2009: {
2012:   if (!m || !n) return 0;
2018:   MatCheckPreallocated(mat, 1);

2020:   PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2021:   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2022:   PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2023:   return 0;
2024: }

2026: /*@C
2027:    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2028:      defined previously by `MatSetLocalToGlobalMapping()`

2030:    Not Collective

2032:    Input Parameters:
2033: +  mat - the matrix
2034: .  nrow, irow - number of rows and their local indices
2035: -  ncol, icol - number of columns and their local indices

2037:    Output Parameter:
2038: .  y -  a logically two-dimensional array of values

2040:    Notes:
2041:      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.

2043:      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2044:      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2045:      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2046:      with `MatSetLocalToGlobalMapping()`.

2048:    Developer Note:
2049:       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2050:       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.

2052:    Level: advanced

2054: .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2055:           `MatSetValuesLocal()`, `MatGetValues()`
2056: @*/
2057: PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2058: {
2062:   MatCheckPreallocated(mat, 1);
2063:   if (!nrow || !ncol) return 0; /* no values to retrieve */
2066:   if (PetscDefined(USE_DEBUG)) {
2069:   }
2071:   PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2072:   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2073:   else {
2074:     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2075:     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2076:       irowm = buf;
2077:       icolm = buf + nrow;
2078:     } else {
2079:       PetscMalloc2(nrow, &bufr, ncol, &bufc);
2080:       irowm = bufr;
2081:       icolm = bufc;
2082:     }
2085:     ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm);
2086:     ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm);
2087:     MatGetValues(mat, nrow, irowm, ncol, icolm, y);
2088:     PetscFree2(bufr, bufc);
2089:   }
2090:   PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2091:   return 0;
2092: }

2094: /*@
2095:   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2096:   the same size. Currently, this can only be called once and creates the given matrix.

2098:   Not Collective

2100:   Input Parameters:
2101: + mat - the matrix
2102: . nb - the number of blocks
2103: . bs - the number of rows (and columns) in each block
2104: . rows - a concatenation of the rows for each block
2105: - v - a concatenation of logically two-dimensional arrays of values

2107:   Note:
2108:   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values

2110:   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.

2112:   Level: advanced

2114: .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2115:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2116: @*/
2117: PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2118: {
2123:   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");

2125:   PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0);
2126:   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2127:   else {
2128:     for (PetscInt b = 0; b < nb; ++b) MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES);
2129:   }
2130:   PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0);
2131:   return 0;
2132: }

2134: /*@
2135:    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2136:    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2137:    using a local (per-processor) numbering.

2139:    Not Collective

2141:    Input Parameters:
2142: +  x - the matrix
2143: .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2144: -  cmapping - column mapping

2146:    Level: intermediate

2148:    Note:
2149:    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix

2151: .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2152: @*/
2153: PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2154: {
2159:   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2160:   else {
2161:     PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping);
2162:     PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping);
2163:   }
2164:   return 0;
2165: }

2167: /*@
2168:    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`

2170:    Not Collective

2172:    Input Parameter:
2173: .  A - the matrix

2175:    Output Parameters:
2176: + rmapping - row mapping
2177: - cmapping - column mapping

2179:    Level: advanced

2181: .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2182: @*/
2183: PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2184: {
2187:   if (rmapping) {
2189:     *rmapping = A->rmap->mapping;
2190:   }
2191:   if (cmapping) {
2193:     *cmapping = A->cmap->mapping;
2194:   }
2195:   return 0;
2196: }

2198: /*@
2199:    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix

2201:    Logically Collective on A

2203:    Input Parameters:
2204: +  A - the matrix
2205: . rmap - row layout
2206: - cmap - column layout

2208:    Level: advanced

2210:    Note:
2211:    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.

2213: .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2214: @*/
2215: PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2216: {
2218:   PetscLayoutReference(rmap, &A->rmap);
2219:   PetscLayoutReference(cmap, &A->cmap);
2220:   return 0;
2221: }

2223: /*@
2224:    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns

2226:    Not Collective

2228:    Input Parameter:
2229: .  A - the matrix

2231:    Output Parameters:
2232: + rmap - row layout
2233: - cmap - column layout

2235:    Level: advanced

2237: .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2238: @*/
2239: PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2240: {
2243:   if (rmap) {
2245:     *rmap = A->rmap;
2246:   }
2247:   if (cmap) {
2249:     *cmap = A->cmap;
2250:   }
2251:   return 0;
2252: }

2254: /*@C
2255:    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2256:    using a local numbering of the nodes.

2258:    Not Collective

2260:    Input Parameters:
2261: +  mat - the matrix
2262: .  nrow, irow - number of rows and their local indices
2263: .  ncol, icol - number of columns and their local indices
2264: .  y -  a logically two-dimensional array of values
2265: -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

2267:    Notes:
2268:    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2269:       `MatSetUp()` before using this routine

2271:    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine

2273:    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2274:    options cannot be mixed without intervening calls to the assembly
2275:    routines.

2277:    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2278:    MUST be called after all calls to `MatSetValuesLocal()` have been completed.

2280:    Level: intermediate

2282:    Developer Note:
2283:     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2284:                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.

2286: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2287:           `MatGetValuesLocal()`
2288: @*/
2289: PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2290: {
2294:   MatCheckPreallocated(mat, 1);
2295:   if (!nrow || !ncol) return 0; /* no values to insert */
2298:   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2300:   if (PetscDefined(USE_DEBUG)) {
2303:   }

2305:   if (mat->assembled) {
2306:     mat->was_assembled = PETSC_TRUE;
2307:     mat->assembled     = PETSC_FALSE;
2308:   }
2309:   PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2310:   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2311:   else {
2312:     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2313:     const PetscInt *irowm, *icolm;

2315:     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2316:       bufr  = buf;
2317:       bufc  = buf + nrow;
2318:       irowm = bufr;
2319:       icolm = bufc;
2320:     } else {
2321:       PetscMalloc2(nrow, &bufr, ncol, &bufc);
2322:       irowm = bufr;
2323:       icolm = bufc;
2324:     }
2325:     if (mat->rmap->mapping) ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr);
2326:     else irowm = irow;
2327:     if (mat->cmap->mapping) {
2328:       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2329:         ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc);
2330:       } else icolm = irowm;
2331:     } else icolm = icol;
2332:     MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv);
2333:     if (bufr != buf) PetscFree2(bufr, bufc);
2334:   }
2335:   PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2336:   return 0;
2337: }

2339: /*@C
2340:    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2341:    using a local ordering of the nodes a block at a time.

2343:    Not Collective

2345:    Input Parameters:
2346: +  x - the matrix
2347: .  nrow, irow - number of rows and their local indices
2348: .  ncol, icol - number of columns and their local indices
2349: .  y -  a logically two-dimensional array of values
2350: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

2352:    Notes:
2353:    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2354:       `MatSetUp()` before using this routine

2356:    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2357:       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the

2359:    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2360:    options cannot be mixed without intervening calls to the assembly
2361:    routines.

2363:    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2364:    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.

2366:    Level: intermediate

2368:    Developer Note:
2369:     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2370:                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.

2372: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2373:           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2374: @*/
2375: PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2376: {
2380:   MatCheckPreallocated(mat, 1);
2381:   if (!nrow || !ncol) return 0; /* no values to insert */
2384:   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2386:   if (PetscDefined(USE_DEBUG)) {
2389:   }

2391:   if (mat->assembled) {
2392:     mat->was_assembled = PETSC_TRUE;
2393:     mat->assembled     = PETSC_FALSE;
2394:   }
2395:   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2396:     PetscInt irbs, rbs;
2397:     MatGetBlockSizes(mat, &rbs, NULL);
2398:     ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs);
2400:   }
2401:   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2402:     PetscInt icbs, cbs;
2403:     MatGetBlockSizes(mat, NULL, &cbs);
2404:     ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs);
2406:   }
2407:   PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2408:   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2409:   else {
2410:     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2411:     const PetscInt *irowm, *icolm;

2413:     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2414:       bufr  = buf;
2415:       bufc  = buf + nrow;
2416:       irowm = bufr;
2417:       icolm = bufc;
2418:     } else {
2419:       PetscMalloc2(nrow, &bufr, ncol, &bufc);
2420:       irowm = bufr;
2421:       icolm = bufc;
2422:     }
2423:     if (mat->rmap->mapping) ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr);
2424:     else irowm = irow;
2425:     if (mat->cmap->mapping) {
2426:       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2427:         ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc);
2428:       } else icolm = irowm;
2429:     } else icolm = icol;
2430:     MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv);
2431:     if (bufr != buf) PetscFree2(bufr, bufc);
2432:   }
2433:   PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2434:   return 0;
2435: }

2437: /*@
2438:    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal

2440:    Collective on mat

2442:    Input Parameters:
2443: +  mat - the matrix
2444: -  x   - the vector to be multiplied

2446:    Output Parameters:
2447: .  y - the result

2449:    Note:
2450:    The vectors x and y cannot be the same.  I.e., one cannot
2451:    call `MatMultDiagonalBlock`(A,y,y).

2453:    Level: developer

2455: .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2456: @*/
2457: PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2458: {

2467:   MatCheckPreallocated(mat, 1);

2469:   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2470:   PetscObjectStateIncrease((PetscObject)y);
2471:   return 0;
2472: }

2474: /* --------------------------------------------------------*/
2475: /*@
2476:    MatMult - Computes the matrix-vector product, y = Ax.

2478:    Neighbor-wise Collective on mat

2480:    Input Parameters:
2481: +  mat - the matrix
2482: -  x   - the vector to be multiplied

2484:    Output Parameters:
2485: .  y - the result

2487:    Note:
2488:    The vectors x and y cannot be the same.  I.e., one cannot
2489:    call `MatMult`(A,y,y).

2491:    Level: beginner

2493: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2494: @*/
2495: PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2496: {
2508:   VecSetErrorIfLocked(y, 3);
2509:   if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2510:   MatCheckPreallocated(mat, 1);

2512:   VecLockReadPush(x);
2513:   PetscLogEventBegin(MAT_Mult, mat, x, y, 0);
2514:   PetscUseTypeMethod(mat, mult, x, y);
2515:   PetscLogEventEnd(MAT_Mult, mat, x, y, 0);
2516:   if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2517:   VecLockReadPop(x);
2518:   return 0;
2519: }

2521: /*@
2522:    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.

2524:    Neighbor-wise Collective on mat

2526:    Input Parameters:
2527: +  mat - the matrix
2528: -  x   - the vector to be multiplied

2530:    Output Parameters:
2531: .  y - the result

2533:    Notes:
2534:    The vectors x and y cannot be the same.  I.e., one cannot
2535:    call `MatMultTranspose`(A,y,y).

2537:    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2538:    use `MatMultHermitianTranspose()`

2540:    Level: beginner

2542: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2543: @*/
2544: PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2545: {
2546:   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;


2560:   if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2561:   MatCheckPreallocated(mat, 1);

2563:   if (!mat->ops->multtranspose) {
2564:     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2566:   } else op = mat->ops->multtranspose;
2567:   PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0);
2568:   VecLockReadPush(x);
2569:   (*op)(mat, x, y);
2570:   VecLockReadPop(x);
2571:   PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0);
2572:   PetscObjectStateIncrease((PetscObject)y);
2573:   if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2574:   return 0;
2575: }

2577: /*@
2578:    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.

2580:    Neighbor-wise Collective on mat

2582:    Input Parameters:
2583: +  mat - the matrix
2584: -  x   - the vector to be multilplied

2586:    Output Parameters:
2587: .  y - the result

2589:    Notes:
2590:    The vectors x and y cannot be the same.  I.e., one cannot
2591:    call `MatMultHermitianTranspose`(A,y,y).

2593:    Also called the conjugate transpose, complex conjugate transpose, or adjoint.

2595:    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.

2597:    Level: beginner

2599: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2600: @*/
2601: PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2602: {

2615:   MatCheckPreallocated(mat, 1);

2617:   PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0);
2618: #if defined(PETSC_USE_COMPLEX)
2619:   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2620:     VecLockReadPush(x);
2621:     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2622:     else PetscUseTypeMethod(mat, mult, x, y);
2623:     VecLockReadPop(x);
2624:   } else {
2625:     Vec w;
2626:     VecDuplicate(x, &w);
2627:     VecCopy(x, w);
2628:     VecConjugate(w);
2629:     MatMultTranspose(mat, w, y);
2630:     VecDestroy(&w);
2631:     VecConjugate(y);
2632:   }
2633:   PetscObjectStateIncrease((PetscObject)y);
2634: #else
2635:   MatMultTranspose(mat, x, y);
2636: #endif
2637:   PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0);
2638:   return 0;
2639: }

2641: /*@
2642:     MatMultAdd -  Computes v3 = v2 + A * v1.

2644:     Neighbor-wise Collective on mat

2646:     Input Parameters:
2647: +   mat - the matrix
2648: -   v1, v2 - the vectors

2650:     Output Parameters:
2651: .   v3 - the result

2653:     Note:
2654:     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2655:     call `MatMultAdd`(A,v1,v2,v1).

2657:     Level: beginner

2659: .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2660: @*/
2661: PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2662: {

2677:   MatCheckPreallocated(mat, 1);

2679:   PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3);
2680:   VecLockReadPush(v1);
2681:   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2682:   VecLockReadPop(v1);
2683:   PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3);
2684:   PetscObjectStateIncrease((PetscObject)v3);
2685:   return 0;
2686: }

2688: /*@
2689:    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.

2691:    Neighbor-wise Collective on mat

2693:    Input Parameters:
2694: +  mat - the matrix
2695: -  v1, v2 - the vectors

2697:    Output Parameters:
2698: .  v3 - the result

2700:    Note:
2701:    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2702:    call `MatMultTransposeAdd`(A,v1,v2,v1).

2704:    Level: beginner

2706: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2707: @*/
2708: PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2709: {
2710:   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;


2725:   MatCheckPreallocated(mat, 1);

2727:   PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3);
2728:   VecLockReadPush(v1);
2729:   (*op)(mat, v1, v2, v3);
2730:   VecLockReadPop(v1);
2731:   PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3);
2732:   PetscObjectStateIncrease((PetscObject)v3);
2733:   return 0;
2734: }

2736: /*@
2737:    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.

2739:    Neighbor-wise Collective on mat

2741:    Input Parameters:
2742: +  mat - the matrix
2743: -  v1, v2 - the vectors

2745:    Output Parameters:
2746: .  v3 - the result

2748:    Note:
2749:    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2750:    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).

2752:    Level: beginner

2754: .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2755: @*/
2756: PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2757: {

2770:   MatCheckPreallocated(mat, 1);

2772:   PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2773:   VecLockReadPush(v1);
2774:   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2775:   else {
2776:     Vec w, z;
2777:     VecDuplicate(v1, &w);
2778:     VecCopy(v1, w);
2779:     VecConjugate(w);
2780:     VecDuplicate(v3, &z);
2781:     MatMultTranspose(mat, w, z);
2782:     VecDestroy(&w);
2783:     VecConjugate(z);
2784:     if (v2 != v3) {
2785:       VecWAXPY(v3, 1.0, v2, z);
2786:     } else {
2787:       VecAXPY(v3, 1.0, z);
2788:     }
2789:     VecDestroy(&z);
2790:   }
2791:   VecLockReadPop(v1);
2792:   PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2793:   PetscObjectStateIncrease((PetscObject)v3);
2794:   return 0;
2795: }

2797: /*@C
2798:    MatGetFactorType - gets the type of factorization it is

2800:    Not Collective

2802:    Input Parameters:
2803: .  mat - the matrix

2805:    Output Parameters:
2806: .  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`

2808:    Level: intermediate

2810: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2811:           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2812: @*/
2813: PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2814: {
2818:   *t = mat->factortype;
2819:   return 0;
2820: }

2822: /*@C
2823:    MatSetFactorType - sets the type of factorization it is

2825:    Logically Collective on mat

2827:    Input Parameters:
2828: +  mat - the matrix
2829: -  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`

2831:    Level: intermediate

2833: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2834:           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2835: @*/
2836: PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2837: {
2840:   mat->factortype = t;
2841:   return 0;
2842: }

2844: /* ------------------------------------------------------------*/
2845: /*@C
2846:    MatGetInfo - Returns information about matrix storage (number of
2847:    nonzeros, memory, etc.).

2849:    Collective on mat if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag

2851:    Input Parameter:
2852: .  mat - the matrix

2854:    Output Parameters:
2855: +  flag - flag indicating the type of parameters to be returned
2856:    (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors,
2857:    MAT_GLOBAL_SUM - sum over all processors)
2858: -  info - matrix information context

2860:    Notes:
2861:    The `MatInfo` context contains a variety of matrix data, including
2862:    number of nonzeros allocated and used, number of mallocs during
2863:    matrix assembly, etc.  Additional information for factored matrices
2864:    is provided (such as the fill ratio, number of mallocs during
2865:    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2866:    when using the runtime options
2867: $       -info -mat_view ::ascii_info

2869:    Example for C/C++ Users:
2870:    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2871:    data within the MatInfo context.  For example,
2872: .vb
2873:       MatInfo info;
2874:       Mat     A;
2875:       double  mal, nz_a, nz_u;

2877:       MatGetInfo(A,MAT_LOCAL,&info);
2878:       mal  = info.mallocs;
2879:       nz_a = info.nz_allocated;
2880: .ve

2882:    Example for Fortran Users:
2883:    Fortran users should declare info as a double precision
2884:    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2885:    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2886:    a complete list of parameter names.
2887: .vb
2888:       double  precision info(MAT_INFO_SIZE)
2889:       double  precision mal, nz_a
2890:       Mat     A
2891:       integer ierr

2893:       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2894:       mal = info(MAT_INFO_MALLOCS)
2895:       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2896: .ve

2898:     Level: intermediate

2900:     Developer Note: fortran interface is not autogenerated as the f90
2901:     interface definition cannot be generated correctly [due to MatInfo]

2903: .seealso: `MatInfo`, `MatStashGetInfo()`
2904: @*/
2905: PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2906: {
2910:   MatCheckPreallocated(mat, 1);
2911:   PetscUseTypeMethod(mat, getinfo, flag, info);
2912:   return 0;
2913: }

2915: /*
2916:    This is used by external packages where it is not easy to get the info from the actual
2917:    matrix factorization.
2918: */
2919: PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2920: {
2921:   PetscMemzero(info, sizeof(MatInfo));
2922:   return 0;
2923: }

2925: /* ----------------------------------------------------------*/

2927: /*@C
2928:    MatLUFactor - Performs in-place LU factorization of matrix.

2930:    Collective on mat

2932:    Input Parameters:
2933: +  mat - the matrix
2934: .  row - row permutation
2935: .  col - column permutation
2936: -  info - options for factorization, includes
2937: $          fill - expected fill as ratio of original fill.
2938: $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2939: $                   Run with the option -info to determine an optimal value to use

2941:    Notes:
2942:    Most users should employ the `KSP` interface for linear solvers
2943:    instead of working directly with matrix algebra routines such as this.
2944:    See, e.g., `KSPCreate()`.

2946:    This changes the state of the matrix to a factored matrix; it cannot be used
2947:    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.

2949:    This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
2950:    when not using `KSP`.

2952:    Level: developer

2954:    Developer Note:
2955:    The Fortran interface is not autogenerated as the f90
2956:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

2958: .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2959:           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2960: @*/
2961: PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
2962: {
2963:   MatFactorInfo tinfo;

2972:   MatCheckPreallocated(mat, 1);
2973:   if (!info) {
2974:     MatFactorInfoInitialize(&tinfo);
2975:     info = &tinfo;
2976:   }

2978:   PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0);
2979:   PetscUseTypeMethod(mat, lufactor, row, col, info);
2980:   PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0);
2981:   PetscObjectStateIncrease((PetscObject)mat);
2982:   return 0;
2983: }

2985: /*@C
2986:    MatILUFactor - Performs in-place ILU factorization of matrix.

2988:    Collective on mat

2990:    Input Parameters:
2991: +  mat - the matrix
2992: .  row - row permutation
2993: .  col - column permutation
2994: -  info - structure containing
2995: $      levels - number of levels of fill.
2996: $      expected fill - as ratio of original fill.
2997: $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
2998:                 missing diagonal entries)

3000:    Notes:
3001:    Most users should employ the `KSP` interface for linear solvers
3002:    instead of working directly with matrix algebra routines such as this.
3003:    See, e.g., `KSPCreate()`.

3005:    Probably really in-place only when level of fill is zero, otherwise allocates
3006:    new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3007:    when not using `KSP`.

3009:    Level: developer

3011:    Developer Note:
3012:    The Fortran interface is not autogenerated as the f90
3013:    interface definition cannot be generated correctly [due to MatFactorInfo]

3015: .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3016: @*/
3017: PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3018: {
3027:   MatCheckPreallocated(mat, 1);

3029:   PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0);
3030:   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3031:   PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0);
3032:   PetscObjectStateIncrease((PetscObject)mat);
3033:   return 0;
3034: }

3036: /*@C
3037:    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3038:    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.

3040:    Collective on fact

3042:    Input Parameters:
3043: +  fact - the factor matrix obtained with `MatGetFactor()`
3044: .  mat - the matrix
3045: .  row, col - row and column permutations
3046: -  info - options for factorization, includes
3047: .vb
3048:           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3049:           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3050: .ve

3052:    Notes:
3053:     See [Matrix Factorization](sec_matfactor) for additional information about factorizations

3055:    Most users should employ the simplified `KSP` interface for linear solvers
3056:    instead of working directly with matrix algebra routines such as this.
3057:    See, e.g., `KSPCreate()`.

3059:    Level: developer

3061:    Developer Note:
3062:    The Fortran interface is not autogenerated as the f90
3063:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3065: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3066: @*/
3067: PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3068: {
3069:   MatFactorInfo tinfo;

3079:   if (!(fact)->ops->lufactorsymbolic) {
3080:     MatSolverType stype;
3081:     MatFactorGetSolverType(fact, &stype);
3082:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3083:   }
3084:   MatCheckPreallocated(mat, 2);
3085:   if (!info) {
3086:     MatFactorInfoInitialize(&tinfo);
3087:     info = &tinfo;
3088:   }

3090:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0);
3091:   (fact->ops->lufactorsymbolic)(fact, mat, row, col, info);
3092:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0);
3093:   PetscObjectStateIncrease((PetscObject)fact);
3094:   return 0;
3095: }

3097: /*@C
3098:    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3099:    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.

3101:    Collective on fact

3103:    Input Parameters:
3104: +  fact - the factor matrix obtained with `MatGetFactor()`
3105: .  mat - the matrix
3106: -  info - options for factorization

3108:    Notes:
3109:    See `MatLUFactor()` for in-place factorization.  See
3110:    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.

3112:    Most users should employ the `KSP` interface for linear solvers
3113:    instead of working directly with matrix algebra routines such as this.
3114:    See, e.g., `KSPCreate()`.

3116:    Level: developer

3118:     Developer Note:
3119:     The Fortran interface is not autogenerated as the f90
3120:     interface definition cannot be generated correctly [due to `MatFactorInfo`]

3122: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3123: @*/
3124: PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3125: {
3126:   MatFactorInfo tinfo;

3134:              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);

3137:   MatCheckPreallocated(mat, 2);
3138:   if (!info) {
3139:     MatFactorInfoInitialize(&tinfo);
3140:     info = &tinfo;
3141:   }

3143:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0);
3144:   else PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0);
3145:   (fact->ops->lufactornumeric)(fact, mat, info);
3146:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0);
3147:   else PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0);
3148:   MatViewFromOptions(fact, NULL, "-mat_factor_view");
3149:   PetscObjectStateIncrease((PetscObject)fact);
3150:   return 0;
3151: }

3153: /*@C
3154:    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3155:    symmetric matrix.

3157:    Collective on mat

3159:    Input Parameters:
3160: +  mat - the matrix
3161: .  perm - row and column permutations
3162: -  f - expected fill as ratio of original fill

3164:    Notes:
3165:    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3166:    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.

3168:    Most users should employ the `KSP` interface for linear solvers
3169:    instead of working directly with matrix algebra routines such as this.
3170:    See, e.g., `KSPCreate()`.

3172:    Level: developer

3174:    Developer Note:
3175:    The Fortran interface is not autogenerated as the f90
3176:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3178: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3179:           `MatGetOrdering()`
3180: @*/
3181: PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3182: {
3183:   MatFactorInfo tinfo;

3192:   MatCheckPreallocated(mat, 1);
3193:   if (!info) {
3194:     MatFactorInfoInitialize(&tinfo);
3195:     info = &tinfo;
3196:   }

3198:   PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0);
3199:   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3200:   PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0);
3201:   PetscObjectStateIncrease((PetscObject)mat);
3202:   return 0;
3203: }

3205: /*@C
3206:    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3207:    of a symmetric matrix.

3209:    Collective on fact

3211:    Input Parameters:
3212: +  fact - the factor matrix obtained with `MatGetFactor()`
3213: .  mat - the matrix
3214: .  perm - row and column permutations
3215: -  info - options for factorization, includes
3216: $          fill - expected fill as ratio of original fill.
3217: $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3218: $                   Run with the option -info to determine an optimal value to use

3220:    Notes:
3221:    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3222:    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.

3224:    Most users should employ the `KSP` interface for linear solvers
3225:    instead of working directly with matrix algebra routines such as this.
3226:    See, e.g., `KSPCreate()`.

3228:    Level: developer

3230:    Developer Note:
3231:    The Fortran interface is not autogenerated as the f90
3232:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3234: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3235:           `MatGetOrdering()`
3236: @*/
3237: PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3238: {
3239:   MatFactorInfo tinfo;

3249:   if (!(fact)->ops->choleskyfactorsymbolic) {
3250:     MatSolverType stype;
3251:     MatFactorGetSolverType(fact, &stype);
3252:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3253:   }
3254:   MatCheckPreallocated(mat, 2);
3255:   if (!info) {
3256:     MatFactorInfoInitialize(&tinfo);
3257:     info = &tinfo;
3258:   }

3260:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3261:   (fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info);
3262:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3263:   PetscObjectStateIncrease((PetscObject)fact);
3264:   return 0;
3265: }

3267: /*@C
3268:    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3269:    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3270:    `MatCholeskyFactorSymbolic()`.

3272:    Collective on fact

3274:    Input Parameters:
3275: +  fact - the factor matrix obtained with `MatGetFactor()`
3276: .  mat - the initial matrix
3277: .  info - options for factorization
3278: -  fact - the symbolic factor of mat

3280:    Note:
3281:    Most users should employ the `KSP` interface for linear solvers
3282:    instead of working directly with matrix algebra routines such as this.
3283:    See, e.g., `KSPCreate()`.

3285:    Level: developer

3287:    Developer Note:
3288:    The Fortran interface is not autogenerated as the f90
3289:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3291: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3292: @*/
3293: PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3294: {
3295:   MatFactorInfo tinfo;

3304:              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3305:   MatCheckPreallocated(mat, 2);
3306:   if (!info) {
3307:     MatFactorInfoInitialize(&tinfo);
3308:     info = &tinfo;
3309:   }

3311:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3312:   else PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0);
3313:   (fact->ops->choleskyfactornumeric)(fact, mat, info);
3314:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3315:   else PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0);
3316:   MatViewFromOptions(fact, NULL, "-mat_factor_view");
3317:   PetscObjectStateIncrease((PetscObject)fact);
3318:   return 0;
3319: }

3321: /*@
3322:    MatQRFactor - Performs in-place QR factorization of matrix.

3324:    Collective on mat

3326:    Input Parameters:
3327: +  mat - the matrix
3328: .  col - column permutation
3329: -  info - options for factorization, includes
3330: $          fill - expected fill as ratio of original fill.
3331: $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3332: $                   Run with the option -info to determine an optimal value to use

3334:    Notes:
3335:    Most users should employ the `KSP` interface for linear solvers
3336:    instead of working directly with matrix algebra routines such as this.
3337:    See, e.g., `KSPCreate()`.

3339:    This changes the state of the matrix to a factored matrix; it cannot be used
3340:    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.

3342:    Level: developer

3344:    Developer Note:
3345:    The Fortran interface is not autogenerated as the f90
3346:    interface definition cannot be generated correctly [due to MatFactorInfo]

3348: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3349:           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3350: @*/
3351: PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3352: {
3359:   MatCheckPreallocated(mat, 1);
3360:   PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0);
3361:   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3362:   PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0);
3363:   PetscObjectStateIncrease((PetscObject)mat);
3364:   return 0;
3365: }

3367: /*@
3368:    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3369:    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.

3371:    Collective on fact

3373:    Input Parameters:
3374: +  fact - the factor matrix obtained with `MatGetFactor()`
3375: .  mat - the matrix
3376: .  col - column permutation
3377: -  info - options for factorization, includes
3378: $          fill - expected fill as ratio of original fill.
3379: $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3380: $                   Run with the option -info to determine an optimal value to use

3382:    Most users should employ the `KSP` interface for linear solvers
3383:    instead of working directly with matrix algebra routines such as this.
3384:    See, e.g., `KSPCreate()`.

3386:    Level: developer

3388:    Developer Note:
3389:    The Fortran interface is not autogenerated as the f90
3390:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3392: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3393: @*/
3394: PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3395: {
3396:   MatFactorInfo tinfo;

3405:   MatCheckPreallocated(mat, 2);
3406:   if (!info) {
3407:     MatFactorInfoInitialize(&tinfo);
3408:     info = &tinfo;
3409:   }

3411:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0);
3412:   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3413:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0);
3414:   PetscObjectStateIncrease((PetscObject)fact);
3415:   return 0;
3416: }

3418: /*@
3419:    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3420:    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.

3422:    Collective on fact

3424:    Input Parameters:
3425: +  fact - the factor matrix obtained with `MatGetFactor()`
3426: .  mat - the matrix
3427: -  info - options for factorization

3429:    Notes:
3430:    See `MatQRFactor()` for in-place factorization.

3432:    Most users should employ the `KSP` interface for linear solvers
3433:    instead of working directly with matrix algebra routines such as this.
3434:    See, e.g., `KSPCreate()`.

3436:    Level: developer

3438:    Developer Note:
3439:    The Fortran interface is not autogenerated as the f90
3440:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3442: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3443: @*/
3444: PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3445: {
3446:   MatFactorInfo tinfo;

3454:              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);

3456:   MatCheckPreallocated(mat, 2);
3457:   if (!info) {
3458:     MatFactorInfoInitialize(&tinfo);
3459:     info = &tinfo;
3460:   }

3462:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0);
3463:   else PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0);
3464:   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3465:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0);
3466:   else PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0);
3467:   MatViewFromOptions(fact, NULL, "-mat_factor_view");
3468:   PetscObjectStateIncrease((PetscObject)fact);
3469:   return 0;
3470: }

3472: /* ----------------------------------------------------------------*/
3473: /*@
3474:    MatSolve - Solves A x = b, given a factored matrix.

3476:    Neighbor-wise Collective on mat

3478:    Input Parameters:
3479: +  mat - the factored matrix
3480: -  b - the right-hand-side vector

3482:    Output Parameter:
3483: .  x - the result vector

3485:    Notes:
3486:    The vectors b and x cannot be the same.  I.e., one cannot
3487:    call `MatSolve`(A,x,x).

3489:    Most users should employ the `KSP` interface for linear solvers
3490:    instead of working directly with matrix algebra routines such as this.
3491:    See, e.g., `KSPCreate()`.

3493:    Level: developer

3495: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3496: @*/
3497: PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3498: {
3509:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3510:   MatCheckPreallocated(mat, 1);

3512:   PetscLogEventBegin(MAT_Solve, mat, b, x, 0);
3513:   if (mat->factorerrortype) {
3514:     PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3515:     VecSetInf(x);
3516:   } else PetscUseTypeMethod(mat, solve, b, x);
3517:   PetscLogEventEnd(MAT_Solve, mat, b, x, 0);
3518:   PetscObjectStateIncrease((PetscObject)x);
3519:   return 0;
3520: }

3522: static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3523: {
3524:   Vec      b, x;
3525:   PetscInt N, i;
3526:   PetscErrorCode (*f)(Mat, Vec, Vec);
3527:   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;

3529:   if (A->factorerrortype) {
3530:     PetscInfo(A, "MatFactorError %d\n", A->factorerrortype);
3531:     MatSetInf(X);
3532:     return 0;
3533:   }
3534:   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3536:   MatBoundToCPU(A, &Abound);
3537:   if (!Abound) {
3538:     PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "");
3539:     PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "");
3540:   }
3541: #if defined(PETSC_HAVE_CUDA)
3542:   if (Bneedconv) MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B);
3543:   if (Xneedconv) MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X);
3544: #elif (PETSC_HAVE_HIP)
3545:   if (Bneedconv) MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B);
3546:   if (Xneedconv) MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X);
3547: #endif
3548:   MatGetSize(B, NULL, &N);
3549:   for (i = 0; i < N; i++) {
3550:     MatDenseGetColumnVecRead(B, i, &b);
3551:     MatDenseGetColumnVecWrite(X, i, &x);
3552:     (*f)(A, b, x);
3553:     MatDenseRestoreColumnVecWrite(X, i, &x);
3554:     MatDenseRestoreColumnVecRead(B, i, &b);
3555:   }
3556:   if (Bneedconv) MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B);
3557:   if (Xneedconv) MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X);
3558:   return 0;
3559: }

3561: /*@
3562:    MatMatSolve - Solves A X = B, given a factored matrix.

3564:    Neighbor-wise Collective on A

3566:    Input Parameters:
3567: +  A - the factored matrix
3568: -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)

3570:    Output Parameter:
3571: .  X - the result matrix (dense matrix)

3573:    Note:
3574:    If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO;
3575:    otherwise, B and X cannot be the same.

3577:    Level: developer

3579: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3580: @*/
3581: PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3582: {
3592:   if (!A->rmap->N && !A->cmap->N) return 0;
3594:   MatCheckPreallocated(A, 1);

3596:   PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3597:   if (!A->ops->matsolve) {
3598:     PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name);
3599:     MatMatSolve_Basic(A, B, X, PETSC_FALSE);
3600:   } else PetscUseTypeMethod(A, matsolve, B, X);
3601:   PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3602:   PetscObjectStateIncrease((PetscObject)X);
3603:   return 0;
3604: }

3606: /*@
3607:    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.

3609:    Neighbor-wise Collective on A

3611:    Input Parameters:
3612: +  A - the factored matrix
3613: -  B - the right-hand-side matrix  (`MATDENSE` matrix)

3615:    Output Parameter:
3616: .  X - the result matrix (dense matrix)

3618:    Note:
3619:    The matrices B and X cannot be the same.  I.e., one cannot
3620:    call `MatMatSolveTranspose`(A,X,X).

3622:    Level: developer

3624: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3625: @*/
3626: PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3627: {
3639:   if (!A->rmap->N && !A->cmap->N) return 0;
3641:   MatCheckPreallocated(A, 1);

3643:   PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3644:   if (!A->ops->matsolvetranspose) {
3645:     PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name);
3646:     MatMatSolve_Basic(A, B, X, PETSC_TRUE);
3647:   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3648:   PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3649:   PetscObjectStateIncrease((PetscObject)X);
3650:   return 0;
3651: }

3653: /*@
3654:    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.

3656:    Neighbor-wise Collective on A

3658:    Input Parameters:
3659: +  A - the factored matrix
3660: -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`

3662:    Output Parameter:
3663: .  X - the result matrix (dense matrix)

3665:    Note:
3666:    For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row
3667:    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.

3669:    Level: developer

3671: .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3672: @*/
3673: PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3674: {

3686:   if (!A->rmap->N && !A->cmap->N) return 0;
3688:   MatCheckPreallocated(A, 1);

3690:   PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0);
3691:   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3692:   PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0);
3693:   PetscObjectStateIncrease((PetscObject)X);
3694:   return 0;
3695: }

3697: /*@
3698:    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3699:                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,

3701:    Neighbor-wise Collective on mat

3703:    Input Parameters:
3704: +  mat - the factored matrix
3705: -  b - the right-hand-side vector

3707:    Output Parameter:
3708: .  x - the result vector

3710:    Notes:
3711:    `MatSolve()` should be used for most applications, as it performs
3712:    a forward solve followed by a backward solve.

3714:    The vectors b and x cannot be the same,  i.e., one cannot
3715:    call `MatForwardSolve`(A,x,x).

3717:    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3718:    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3719:    `MatForwardSolve()` solves U^T*D y = b, and
3720:    `MatBackwardSolve()` solves U x = y.
3721:    Thus they do not provide a symmetric preconditioner.

3723:    Level: developer

3725: .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3726: @*/
3727: PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3728: {
3739:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3740:   MatCheckPreallocated(mat, 1);

3742:   PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0);
3743:   PetscUseTypeMethod(mat, forwardsolve, b, x);
3744:   PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0);
3745:   PetscObjectStateIncrease((PetscObject)x);
3746:   return 0;
3747: }

3749: /*@
3750:    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3751:                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,

3753:    Neighbor-wise Collective on mat

3755:    Input Parameters:
3756: +  mat - the factored matrix
3757: -  b - the right-hand-side vector

3759:    Output Parameter:
3760: .  x - the result vector

3762:    Notes:
3763:    `MatSolve()` should be used for most applications, as it performs
3764:    a forward solve followed by a backward solve.

3766:    The vectors b and x cannot be the same.  I.e., one cannot
3767:    call `MatBackwardSolve`(A,x,x).

3769:    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3770:    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3771:    `MatForwardSolve()` solves U^T*D y = b, and
3772:    `MatBackwardSolve()` solves U x = y.
3773:    Thus they do not provide a symmetric preconditioner.

3775:    Level: developer

3777: .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3778: @*/
3779: PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3780: {
3791:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3792:   MatCheckPreallocated(mat, 1);

3794:   PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0);
3795:   PetscUseTypeMethod(mat, backwardsolve, b, x);
3796:   PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0);
3797:   PetscObjectStateIncrease((PetscObject)x);
3798:   return 0;
3799: }

3801: /*@
3802:    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.

3804:    Neighbor-wise Collective on mat

3806:    Input Parameters:
3807: +  mat - the factored matrix
3808: .  b - the right-hand-side vector
3809: -  y - the vector to be added to

3811:    Output Parameter:
3812: .  x - the result vector

3814:    Note:
3815:    The vectors b and x cannot be the same.  I.e., one cannot
3816:    call `MatSolveAdd`(A,x,y,x).

3818:    Level: developer

3820: .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3821: @*/
3822: PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3823: {
3824:   PetscScalar one = 1.0;
3825:   Vec         tmp;

3841:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3842:   MatCheckPreallocated(mat, 1);

3844:   PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y);
3845:   if (mat->factorerrortype) {
3846:     PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3847:     VecSetInf(x);
3848:   } else if (mat->ops->solveadd) {
3849:     PetscUseTypeMethod(mat, solveadd, b, y, x);
3850:   } else {
3851:     /* do the solve then the add manually */
3852:     if (x != y) {
3853:       MatSolve(mat, b, x);
3854:       VecAXPY(x, one, y);
3855:     } else {
3856:       VecDuplicate(x, &tmp);
3857:       VecCopy(x, tmp);
3858:       MatSolve(mat, b, x);
3859:       VecAXPY(x, one, tmp);
3860:       VecDestroy(&tmp);
3861:     }
3862:   }
3863:   PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y);
3864:   PetscObjectStateIncrease((PetscObject)x);
3865:   return 0;
3866: }

3868: /*@
3869:    MatSolveTranspose - Solves A' x = b, given a factored matrix.

3871:    Neighbor-wise Collective on mat

3873:    Input Parameters:
3874: +  mat - the factored matrix
3875: -  b - the right-hand-side vector

3877:    Output Parameter:
3878: .  x - the result vector

3880:    Notes:
3881:    The vectors b and x cannot be the same.  I.e., one cannot
3882:    call `MatSolveTranspose`(A,x,x).

3884:    Most users should employ the `KSP` interface for linear solvers
3885:    instead of working directly with matrix algebra routines such as this.
3886:    See, e.g., `KSPCreate()`.

3888:    Level: developer

3890: .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3891: @*/
3892: PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3893: {
3894:   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;

3905:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3906:   MatCheckPreallocated(mat, 1);
3907:   PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0);
3908:   if (mat->factorerrortype) {
3909:     PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3910:     VecSetInf(x);
3911:   } else {
3913:     (*f)(mat, b, x);
3914:   }
3915:   PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0);
3916:   PetscObjectStateIncrease((PetscObject)x);
3917:   return 0;
3918: }

3920: /*@
3921:    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3922:                       factored matrix.

3924:    Neighbor-wise Collective on mat

3926:    Input Parameters:
3927: +  mat - the factored matrix
3928: .  b - the right-hand-side vector
3929: -  y - the vector to be added to

3931:    Output Parameter:
3932: .  x - the result vector

3934:    Note:
3935:    The vectors b and x cannot be the same.  I.e., one cannot
3936:    call `MatSolveTransposeAdd`(A,x,y,x).

3938:    Level: developer

3940: .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
3941: @*/
3942: PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
3943: {
3944:   PetscScalar one = 1.0;
3945:   Vec         tmp;
3946:   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;

3961:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3962:   MatCheckPreallocated(mat, 1);

3964:   PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y);
3965:   if (mat->factorerrortype) {
3966:     PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3967:     VecSetInf(x);
3968:   } else if (f) {
3969:     (*f)(mat, b, y, x);
3970:   } else {
3971:     /* do the solve then the add manually */
3972:     if (x != y) {
3973:       MatSolveTranspose(mat, b, x);
3974:       VecAXPY(x, one, y);
3975:     } else {
3976:       VecDuplicate(x, &tmp);
3977:       VecCopy(x, tmp);
3978:       MatSolveTranspose(mat, b, x);
3979:       VecAXPY(x, one, tmp);
3980:       VecDestroy(&tmp);
3981:     }
3982:   }
3983:   PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y);
3984:   PetscObjectStateIncrease((PetscObject)x);
3985:   return 0;
3986: }
3987: /* ----------------------------------------------------------------*/

3989: /*@
3990:    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.

3992:    Neighbor-wise Collective on mat

3994:    Input Parameters:
3995: +  mat - the matrix
3996: .  b - the right hand side
3997: .  omega - the relaxation factor
3998: .  flag - flag indicating the type of SOR (see below)
3999: .  shift -  diagonal shift
4000: .  its - the number of iterations
4001: -  lits - the number of local iterations

4003:    Output Parameter:
4004: .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)

4006:    SOR Flags:
4007: +     `SOR_FORWARD_SWEEP` - forward SOR
4008: .     `SOR_BACKWARD_SWEEP` - backward SOR
4009: .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4010: .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4011: .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4012: .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4013: .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4014: .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4015:          upper/lower triangular part of matrix to
4016:          vector (with omega)
4017: -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess

4019:    Notes:
4020:    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4021:    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4022:    on each processor.

4024:    Application programmers will not generally use `MatSOR()` directly,
4025:    but instead will employ the `KSP`/`PC` interface.

4027:    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing

4029:    Most users should employ the `KSP` interface for linear solvers
4030:    instead of working directly with matrix algebra routines such as this.
4031:    See, e.g., `KSPCreate()`.

4033:    Vectors x and b CANNOT be the same

4035:    Notes for Advanced Users:
4036:    The flags are implemented as bitwise inclusive or operations.
4037:    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4038:    to specify a zero initial guess for SSOR.

4040:    Developer Note:
4041:    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes

4043:    Level: developer

4045: .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4046: @*/
4047: PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4048: {

4064:   MatCheckPreallocated(mat, 1);
4065:   PetscLogEventBegin(MAT_SOR, mat, b, x, 0);
4066:   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4067:   PetscLogEventEnd(MAT_SOR, mat, b, x, 0);
4068:   PetscObjectStateIncrease((PetscObject)x);
4069:   return 0;
4070: }

4072: /*
4073:       Default matrix copy routine.
4074: */
4075: PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4076: {
4077:   PetscInt           i, rstart = 0, rend = 0, nz;
4078:   const PetscInt    *cwork;
4079:   const PetscScalar *vwork;

4081:   if (B->assembled) MatZeroEntries(B);
4082:   if (str == SAME_NONZERO_PATTERN) {
4083:     MatGetOwnershipRange(A, &rstart, &rend);
4084:     for (i = rstart; i < rend; i++) {
4085:       MatGetRow(A, i, &nz, &cwork, &vwork);
4086:       MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES);
4087:       MatRestoreRow(A, i, &nz, &cwork, &vwork);
4088:     }
4089:   } else {
4090:     MatAYPX(B, 0.0, A, str);
4091:   }
4092:   MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);
4093:   MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);
4094:   return 0;
4095: }

4097: /*@
4098:    MatCopy - Copies a matrix to another matrix.

4100:    Collective on A

4102:    Input Parameters:
4103: +  A - the matrix
4104: -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`

4106:    Output Parameter:
4107: .  B - where the copy is put

4109:    Notes:
4110:    If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.

4112:    `MatCopy()` copies the matrix entries of a matrix to another existing
4113:    matrix (after first zeroing the second matrix).  A related routine is
4114:    `MatConvert()`, which first creates a new matrix and then copies the data.

4116:    Level: intermediate

4118: .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4119: @*/
4120: PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4121: {
4122:   PetscInt i;

4129:   MatCheckPreallocated(B, 2);
4133:              A->cmap->N, B->cmap->N);
4134:   MatCheckPreallocated(A, 1);
4135:   if (A == B) return 0;

4137:   PetscLogEventBegin(MAT_Copy, A, B, 0, 0);
4138:   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4139:   else MatCopy_Basic(A, B, str);

4141:   B->stencil.dim = A->stencil.dim;
4142:   B->stencil.noc = A->stencil.noc;
4143:   for (i = 0; i <= A->stencil.dim; i++) {
4144:     B->stencil.dims[i]   = A->stencil.dims[i];
4145:     B->stencil.starts[i] = A->stencil.starts[i];
4146:   }

4148:   PetscLogEventEnd(MAT_Copy, A, B, 0, 0);
4149:   PetscObjectStateIncrease((PetscObject)B);
4150:   return 0;
4151: }

4153: /*@C
4154:    MatConvert - Converts a matrix to another matrix, either of the same
4155:    or different type.

4157:    Collective on mat

4159:    Input Parameters:
4160: +  mat - the matrix
4161: .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4162:    same type as the original matrix.
4163: -  reuse - denotes if the destination matrix is to be created or reused.
4164:    Use `MAT_INPLACE_MATRIX` for inplace conversion (that is when you want the input mat to be changed to contain the matrix in the new format), otherwise use
4165:    `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` (can only be used after the first call was made with `MAT_INITIAL_MATRIX`, causes the matrix space in M to be reused).

4167:    Output Parameter:
4168: .  M - pointer to place new matrix

4170:    Notes:
4171:    `MatConvert()` first creates a new matrix and then copies the data from
4172:    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4173:    entries of one matrix to another already existing matrix context.

4175:    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4176:    the MPI communicator of the generated matrix is always the same as the communicator
4177:    of the input matrix.

4179:    Level: intermediate

4181: .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4182: @*/
4183: PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4184: {
4185:   PetscBool  sametype, issame, flg;
4186:   PetscBool3 issymmetric, ishermitian;
4187:   char       convname[256], mtype[256];
4188:   Mat        B;

4195:   MatCheckPreallocated(mat, 1);

4197:   PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg);
4198:   if (flg) newtype = mtype;

4200:   PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype);
4201:   PetscStrcmp(newtype, "same", &issame);

4205:   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4206:     PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4207:     return 0;
4208:   }

4210:   /* Cache Mat options because some converters use MatHeaderReplace  */
4211:   issymmetric = mat->symmetric;
4212:   ishermitian = mat->hermitian;

4214:   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4215:     PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4216:     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4217:   } else {
4218:     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4219:     const char *prefix[3]                                 = {"seq", "mpi", ""};
4220:     PetscInt    i;
4221:     /*
4222:        Order of precedence:
4223:        0) See if newtype is a superclass of the current matrix.
4224:        1) See if a specialized converter is known to the current matrix.
4225:        2) See if a specialized converter is known to the desired matrix class.
4226:        3) See if a good general converter is registered for the desired class
4227:           (as of 6/27/03 only MATMPIADJ falls into this category).
4228:        4) See if a good general converter is known for the current matrix.
4229:        5) Use a really basic converter.
4230:     */

4232:     /* 0) See if newtype is a superclass of the current matrix.
4233:           i.e mat is mpiaij and newtype is aij */
4234:     for (i = 0; i < 2; i++) {
4235:       PetscStrncpy(convname, prefix[i], sizeof(convname));
4236:       PetscStrlcat(convname, newtype, sizeof(convname));
4237:       PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg);
4238:       PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg);
4239:       if (flg) {
4240:         if (reuse == MAT_INPLACE_MATRIX) {
4241:           PetscInfo(mat, "Early return\n");
4242:           return 0;
4243:         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4244:           PetscInfo(mat, "Calling MatDuplicate\n");
4245:           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4246:           return 0;
4247:         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4248:           PetscInfo(mat, "Calling MatCopy\n");
4249:           MatCopy(mat, *M, SAME_NONZERO_PATTERN);
4250:           return 0;
4251:         }
4252:       }
4253:     }
4254:     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4255:     for (i = 0; i < 3; i++) {
4256:       PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4257:       PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4258:       PetscStrlcat(convname, "_", sizeof(convname));
4259:       PetscStrlcat(convname, prefix[i], sizeof(convname));
4260:       PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname));
4261:       PetscStrlcat(convname, "_C", sizeof(convname));
4262:       PetscObjectQueryFunction((PetscObject)mat, convname, &conv);
4263:       PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv);
4264:       if (conv) goto foundconv;
4265:     }

4267:     /* 2)  See if a specialized converter is known to the desired matrix class. */
4268:     MatCreate(PetscObjectComm((PetscObject)mat), &B);
4269:     MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
4270:     MatSetType(B, newtype);
4271:     for (i = 0; i < 3; i++) {
4272:       PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4273:       PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4274:       PetscStrlcat(convname, "_", sizeof(convname));
4275:       PetscStrlcat(convname, prefix[i], sizeof(convname));
4276:       PetscStrlcat(convname, newtype, sizeof(convname));
4277:       PetscStrlcat(convname, "_C", sizeof(convname));
4278:       PetscObjectQueryFunction((PetscObject)B, convname, &conv);
4279:       PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv);
4280:       if (conv) {
4281:         MatDestroy(&B);
4282:         goto foundconv;
4283:       }
4284:     }

4286:     /* 3) See if a good general converter is registered for the desired class */
4287:     conv = B->ops->convertfrom;
4288:     PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv);
4289:     MatDestroy(&B);
4290:     if (conv) goto foundconv;

4292:     /* 4) See if a good general converter is known for the current matrix */
4293:     if (mat->ops->convert) conv = mat->ops->convert;
4294:     PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv);
4295:     if (conv) goto foundconv;

4297:     /* 5) Use a really basic converter. */
4298:     PetscInfo(mat, "Using MatConvert_Basic\n");
4299:     conv = MatConvert_Basic;

4301:   foundconv:
4302:     PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4303:     (*conv)(mat, newtype, reuse, M);
4304:     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4305:       /* the block sizes must be same if the mappings are copied over */
4306:       (*M)->rmap->bs = mat->rmap->bs;
4307:       (*M)->cmap->bs = mat->cmap->bs;
4308:       PetscObjectReference((PetscObject)mat->rmap->mapping);
4309:       PetscObjectReference((PetscObject)mat->cmap->mapping);
4310:       (*M)->rmap->mapping = mat->rmap->mapping;
4311:       (*M)->cmap->mapping = mat->cmap->mapping;
4312:     }
4313:     (*M)->stencil.dim = mat->stencil.dim;
4314:     (*M)->stencil.noc = mat->stencil.noc;
4315:     for (i = 0; i <= mat->stencil.dim; i++) {
4316:       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4317:       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4318:     }
4319:     PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4320:   }
4321:   PetscObjectStateIncrease((PetscObject)*M);

4323:   /* Copy Mat options */
4324:   if (issymmetric == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE);
4325:   else if (issymmetric == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE);
4326:   if (ishermitian == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE);
4327:   else if (ishermitian == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE);
4328:   return 0;
4329: }

4331: /*@C
4332:    MatFactorGetSolverType - Returns name of the package providing the factorization routines

4334:    Not Collective

4336:    Input Parameter:
4337: .  mat - the matrix, must be a factored matrix

4339:    Output Parameter:
4340: .   type - the string name of the package (do not free this string)

4342:    Note:
4343:       In Fortran you pass in a empty string and the package name will be copied into it.
4344:     (Make sure the string is long enough)

4346:    Level: intermediate

4348: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4349: @*/
4350: PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4351: {
4352:   PetscErrorCode (*conv)(Mat, MatSolverType *);

4358:   PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv);
4359:   if (conv) (*conv)(mat, type);
4360:   else *type = MATSOLVERPETSC;
4361:   return 0;
4362: }

4364: typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4365: struct _MatSolverTypeForSpecifcType {
4366:   MatType mtype;
4367:   /* no entry for MAT_FACTOR_NONE */
4368:   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4369:   MatSolverTypeForSpecifcType next;
4370: };

4372: typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4373: struct _MatSolverTypeHolder {
4374:   char                       *name;
4375:   MatSolverTypeForSpecifcType handlers;
4376:   MatSolverTypeHolder         next;
4377: };

4379: static MatSolverTypeHolder MatSolverTypeHolders = NULL;

4381: /*@C
4382:    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type

4384:    Input Parameters:
4385: +    package - name of the package, for example petsc or superlu
4386: .    mtype - the matrix type that works with this package
4387: .    ftype - the type of factorization supported by the package
4388: -    createfactor - routine that will create the factored matrix ready to be used

4390:     Level: developer

4392: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4393: @*/
4394: PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4395: {
4396:   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4397:   PetscBool                   flg;
4398:   MatSolverTypeForSpecifcType inext, iprev = NULL;

4400:   MatInitializePackage();
4401:   if (!next) {
4402:     PetscNew(&MatSolverTypeHolders);
4403:     PetscStrallocpy(package, &MatSolverTypeHolders->name);
4404:     PetscNew(&MatSolverTypeHolders->handlers);
4405:     PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype);
4406:     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4407:     return 0;
4408:   }
4409:   while (next) {
4410:     PetscStrcasecmp(package, next->name, &flg);
4411:     if (flg) {
4413:       inext = next->handlers;
4414:       while (inext) {
4415:         PetscStrcasecmp(mtype, inext->mtype, &flg);
4416:         if (flg) {
4417:           inext->createfactor[(int)ftype - 1] = createfactor;
4418:           return 0;
4419:         }
4420:         iprev = inext;
4421:         inext = inext->next;
4422:       }
4423:       PetscNew(&iprev->next);
4424:       PetscStrallocpy(mtype, (char **)&iprev->next->mtype);
4425:       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4426:       return 0;
4427:     }
4428:     prev = next;
4429:     next = next->next;
4430:   }
4431:   PetscNew(&prev->next);
4432:   PetscStrallocpy(package, &prev->next->name);
4433:   PetscNew(&prev->next->handlers);
4434:   PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype);
4435:   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4436:   return 0;
4437: }

4439: /*@C
4440:    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist

4442:    Input Parameters:
4443: +    type - name of the package, for example petsc or superlu
4444: .    ftype - the type of factorization supported by the type
4445: -    mtype - the matrix type that works with this type

4447:    Output Parameters:
4448: +   foundtype - `PETSC_TRUE` if the type was registered
4449: .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4450: -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found

4452:     Level: developer

4454: .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4455: @*/
4456: PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4457: {
4458:   MatSolverTypeHolder         next = MatSolverTypeHolders;
4459:   PetscBool                   flg;
4460:   MatSolverTypeForSpecifcType inext;

4462:   if (foundtype) *foundtype = PETSC_FALSE;
4463:   if (foundmtype) *foundmtype = PETSC_FALSE;
4464:   if (createfactor) *createfactor = NULL;

4466:   if (type) {
4467:     while (next) {
4468:       PetscStrcasecmp(type, next->name, &flg);
4469:       if (flg) {
4470:         if (foundtype) *foundtype = PETSC_TRUE;
4471:         inext = next->handlers;
4472:         while (inext) {
4473:           PetscStrbeginswith(mtype, inext->mtype, &flg);
4474:           if (flg) {
4475:             if (foundmtype) *foundmtype = PETSC_TRUE;
4476:             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4477:             return 0;
4478:           }
4479:           inext = inext->next;
4480:         }
4481:       }
4482:       next = next->next;
4483:     }
4484:   } else {
4485:     while (next) {
4486:       inext = next->handlers;
4487:       while (inext) {
4488:         PetscStrcmp(mtype, inext->mtype, &flg);
4489:         if (flg && inext->createfactor[(int)ftype - 1]) {
4490:           if (foundtype) *foundtype = PETSC_TRUE;
4491:           if (foundmtype) *foundmtype = PETSC_TRUE;
4492:           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4493:           return 0;
4494:         }
4495:         inext = inext->next;
4496:       }
4497:       next = next->next;
4498:     }
4499:     /* try with base classes inext->mtype */
4500:     next = MatSolverTypeHolders;
4501:     while (next) {
4502:       inext = next->handlers;
4503:       while (inext) {
4504:         PetscStrbeginswith(mtype, inext->mtype, &flg);
4505:         if (flg && inext->createfactor[(int)ftype - 1]) {
4506:           if (foundtype) *foundtype = PETSC_TRUE;
4507:           if (foundmtype) *foundmtype = PETSC_TRUE;
4508:           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4509:           return 0;
4510:         }
4511:         inext = inext->next;
4512:       }
4513:       next = next->next;
4514:     }
4515:   }
4516:   return 0;
4517: }

4519: PetscErrorCode MatSolverTypeDestroy(void)
4520: {
4521:   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4522:   MatSolverTypeForSpecifcType inext, iprev;

4524:   while (next) {
4525:     PetscFree(next->name);
4526:     inext = next->handlers;
4527:     while (inext) {
4528:       PetscFree(inext->mtype);
4529:       iprev = inext;
4530:       inext = inext->next;
4531:       PetscFree(iprev);
4532:     }
4533:     prev = next;
4534:     next = next->next;
4535:     PetscFree(prev);
4536:   }
4537:   MatSolverTypeHolders = NULL;
4538:   return 0;
4539: }

4541: /*@C
4542:    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`

4544:    Logically Collective on mat

4546:    Input Parameters:
4547: .  mat - the matrix

4549:    Output Parameters:
4550: .  flg - `PETSC_TRUE` if uses the ordering

4552:    Note:
4553:    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4554:    packages do not, thus we want to skip generating the ordering when it is not needed or used.

4556:    Level: developer

4558: .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4559: @*/
4560: PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4561: {
4562:   *flg = mat->canuseordering;
4563:   return 0;
4564: }

4566: /*@C
4567:    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object

4569:    Logically Collective on mat

4571:    Input Parameters:
4572: .  mat - the matrix obtained with `MatGetFactor()`

4574:    Output Parameters:
4575: .  otype - the preferred type

4577:    Level: developer

4579: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4580: @*/
4581: PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4582: {
4583:   *otype = mat->preferredordering[ftype];
4585:   return 0;
4586: }

4588: /*@C
4589:    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()

4591:    Collective on mat

4593:    Input Parameters:
4594: +  mat - the matrix
4595: .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4596: -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`

4598:    Output Parameters:
4599: .  f - the factor matrix used with MatXXFactorSymbolic() calls

4601:    Options Database Key:
4602: .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4603:                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.

4605:    Notes:
4606:      Users usually access the factorization solvers via `KSP`

4608:       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4609:      such as pastix, superlu, mumps etc.

4611:       PETSc must have been ./configure to use the external solver, using the option --download-package

4613:       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4614:       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4615:       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.

4617:    Developer Note:
4618:       This should actually be called `MatCreateFactor()` since it creates a new factor object

4620:    Level: intermediate

4622: .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4623:           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4624: @*/
4625: PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4626: {
4627:   PetscBool foundtype, foundmtype;
4628:   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);


4634:   MatCheckPreallocated(mat, 1);

4636:   MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv);
4637:   if (!foundtype) {
4638:     if (type) {
4639:       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate solver type %s for factorization type %s and matrix type %s. Perhaps you must ./configure with --download-%s", type, MatFactorTypes[ftype],
4640:               ((PetscObject)mat)->type_name, type);
4641:     } else {
4642:       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate a solver type for factorization type %s and matrix type %s.", MatFactorTypes[ftype], ((PetscObject)mat)->type_name);
4643:     }
4644:   }

4648:   (*conv)(mat, ftype, f);
4649:   if (mat->factorprefix) MatSetOptionsPrefix(*f, mat->factorprefix);
4650:   return 0;
4651: }

4653: /*@C
4654:    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type

4656:    Not Collective

4658:    Input Parameters:
4659: +  mat - the matrix
4660: .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4661: -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`

4663:    Output Parameter:
4664: .    flg - PETSC_TRUE if the factorization is available

4666:    Notes:
4667:       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4668:      such as pastix, superlu, mumps etc.

4670:       PETSc must have been ./configure to use the external solver, using the option --download-package

4672:    Developer Note:
4673:       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object

4675:    Level: intermediate

4677: .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4678:           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4679: @*/
4680: PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4681: {
4682:   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);


4689:   MatCheckPreallocated(mat, 1);

4691:   MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv);
4692:   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4693:   return 0;
4694: }

4696: /*@
4697:    MatDuplicate - Duplicates a matrix including the non-zero structure.

4699:    Collective on mat

4701:    Input Parameters:
4702: +  mat - the matrix
4703: -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4704:         See the manual page for `MatDuplicateOption()` for an explanation of these options.

4706:    Output Parameter:
4707: .  M - pointer to place new matrix

4709:    Level: intermediate

4711:    Notes:
4712:     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.

4714:     May be called with an unassembled input `Mat` if `MAT_DO_NOT_COPY_VALUES` is used, in which case the output `Mat` is unassembled as well.

4716:     When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the simple matrix data structure of mat
4717:     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4718:     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.

4720: .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4721: @*/
4722: PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4723: {
4724:   Mat         B;
4725:   VecType     vtype;
4726:   PetscInt    i;
4727:   PetscObject dm;
4728:   void (*viewf)(void);

4735:   MatCheckPreallocated(mat, 1);

4737:   *M = NULL;
4738:   PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4739:   PetscUseTypeMethod(mat, duplicate, op, M);
4740:   PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4741:   B = *M;

4743:   MatGetOperation(mat, MATOP_VIEW, &viewf);
4744:   if (viewf) MatSetOperation(B, MATOP_VIEW, viewf);
4745:   MatGetVecType(mat, &vtype);
4746:   MatSetVecType(B, vtype);

4748:   B->stencil.dim = mat->stencil.dim;
4749:   B->stencil.noc = mat->stencil.noc;
4750:   for (i = 0; i <= mat->stencil.dim; i++) {
4751:     B->stencil.dims[i]   = mat->stencil.dims[i];
4752:     B->stencil.starts[i] = mat->stencil.starts[i];
4753:   }

4755:   B->nooffproczerorows = mat->nooffproczerorows;
4756:   B->nooffprocentries  = mat->nooffprocentries;

4758:   PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm);
4759:   if (dm) PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm);
4760:   PetscObjectStateIncrease((PetscObject)B);
4761:   return 0;
4762: }

4764: /*@
4765:    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`

4767:    Logically Collective on mat

4769:    Input Parameters:
4770: +  mat - the matrix
4771: -  v - the vector for storing the diagonal

4773:    Output Parameter:
4774: .  v - the diagonal of the matrix

4776:    Level: intermediate

4778:    Note:
4779:    Currently only correct in parallel for square matrices.

4781: .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4782: @*/
4783: PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4784: {
4789:   MatCheckPreallocated(mat, 1);

4791:   PetscUseTypeMethod(mat, getdiagonal, v);
4792:   PetscObjectStateIncrease((PetscObject)v);
4793:   return 0;
4794: }

4796: /*@C
4797:    MatGetRowMin - Gets the minimum value (of the real part) of each
4798:         row of the matrix

4800:    Logically Collective on mat

4802:    Input Parameter:
4803: .  mat - the matrix

4805:    Output Parameters:
4806: +  v - the vector for storing the maximums
4807: -  idx - the indices of the column found for each row (optional)

4809:    Level: intermediate

4811:    Note:
4812:     The result of this call are the same as if one converted the matrix to dense format
4813:       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).

4815:     This code is only implemented for a couple of matrix formats.

4817: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4818:           `MatGetRowMax()`
4819: @*/
4820: PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4821: {

4827:   if (!mat->cmap->N) {
4828:     VecSet(v, PETSC_MAX_REAL);
4829:     if (idx) {
4830:       PetscInt i, m = mat->rmap->n;
4831:       for (i = 0; i < m; i++) idx[i] = -1;
4832:     }
4833:   } else {
4834:     MatCheckPreallocated(mat, 1);
4835:   }
4836:   PetscUseTypeMethod(mat, getrowmin, v, idx);
4837:   PetscObjectStateIncrease((PetscObject)v);
4838:   return 0;
4839: }

4841: /*@C
4842:    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4843:         row of the matrix

4845:    Logically Collective on mat

4847:    Input Parameter:
4848: .  mat - the matrix

4850:    Output Parameters:
4851: +  v - the vector for storing the minimums
4852: -  idx - the indices of the column found for each row (or NULL if not needed)

4854:    Level: intermediate

4856:    Notes:
4857:     if a row is completely empty or has only 0.0 values then the idx[] value for that
4858:     row is 0 (the first column).

4860:     This code is only implemented for a couple of matrix formats.

4862: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4863: @*/
4864: PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4865: {

4872:   if (!mat->cmap->N) {
4873:     VecSet(v, 0.0);
4874:     if (idx) {
4875:       PetscInt i, m = mat->rmap->n;
4876:       for (i = 0; i < m; i++) idx[i] = -1;
4877:     }
4878:   } else {
4879:     MatCheckPreallocated(mat, 1);
4880:     if (idx) PetscArrayzero(idx, mat->rmap->n);
4881:     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4882:   }
4883:   PetscObjectStateIncrease((PetscObject)v);
4884:   return 0;
4885: }

4887: /*@C
4888:    MatGetRowMax - Gets the maximum value (of the real part) of each
4889:         row of the matrix

4891:    Logically Collective on mat

4893:    Input Parameter:
4894: .  mat - the matrix

4896:    Output Parameters:
4897: +  v - the vector for storing the maximums
4898: -  idx - the indices of the column found for each row (optional)

4900:    Level: intermediate

4902:    Notes:
4903:     The result of this call are the same as if one converted the matrix to dense format
4904:       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).

4906:     This code is only implemented for a couple of matrix formats.

4908: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4909: @*/
4910: PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
4911: {

4917:   if (!mat->cmap->N) {
4918:     VecSet(v, PETSC_MIN_REAL);
4919:     if (idx) {
4920:       PetscInt i, m = mat->rmap->n;
4921:       for (i = 0; i < m; i++) idx[i] = -1;
4922:     }
4923:   } else {
4924:     MatCheckPreallocated(mat, 1);
4925:     PetscUseTypeMethod(mat, getrowmax, v, idx);
4926:   }
4927:   PetscObjectStateIncrease((PetscObject)v);
4928:   return 0;
4929: }

4931: /*@C
4932:    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4933:         row of the matrix

4935:    Logically Collective on mat

4937:    Input Parameter:
4938: .  mat - the matrix

4940:    Output Parameters:
4941: +  v - the vector for storing the maximums
4942: -  idx - the indices of the column found for each row (or NULL if not needed)

4944:    Level: intermediate

4946:    Notes:
4947:     if a row is completely empty or has only 0.0 values then the idx[] value for that
4948:     row is 0 (the first column).

4950:     This code is only implemented for a couple of matrix formats.

4952: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4953: @*/
4954: PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
4955: {

4961:   if (!mat->cmap->N) {
4962:     VecSet(v, 0.0);
4963:     if (idx) {
4964:       PetscInt i, m = mat->rmap->n;
4965:       for (i = 0; i < m; i++) idx[i] = -1;
4966:     }
4967:   } else {
4968:     MatCheckPreallocated(mat, 1);
4969:     if (idx) PetscArrayzero(idx, mat->rmap->n);
4970:     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
4971:   }
4972:   PetscObjectStateIncrease((PetscObject)v);
4973:   return 0;
4974: }

4976: /*@
4977:    MatGetRowSum - Gets the sum of each row of the matrix

4979:    Logically or Neighborhood Collective on mat

4981:    Input Parameters:
4982: .  mat - the matrix

4984:    Output Parameter:
4985: .  v - the vector for storing the sum of rows

4987:    Level: intermediate

4989:    Notes:
4990:     This code is slow since it is not currently specialized for different formats

4992: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
4993: @*/
4994: PetscErrorCode MatGetRowSum(Mat mat, Vec v)
4995: {
4996:   Vec ones;

5002:   MatCheckPreallocated(mat, 1);
5003:   MatCreateVecs(mat, &ones, NULL);
5004:   VecSet(ones, 1.);
5005:   MatMult(mat, ones, v);
5006:   VecDestroy(&ones);
5007:   return 0;
5008: }

5010: /*@
5011:    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5012:    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)

5014:    Collective on mat

5016:    Input Parameter:
5017: .  mat - the matrix to provide the transpose

5019:    Output Parameter:
5020: .  mat - the matrix to contain the transpose; it MUST have the nonzero structure of the transpose of A or the code will crash or generate incorrect results

5022:    Level: advanced

5024:    Note:
5025:    Normally he use of `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) requires that B was obtained with a call to `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B). This
5026:    routine allows bypassing that call.

5028: .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5029: @*/
5030: PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5031: {
5032:   PetscContainer  rB = NULL;
5033:   MatParentState *rb = NULL;

5035:   PetscNew(&rb);
5036:   rb->id    = ((PetscObject)mat)->id;
5037:   rb->state = 0;
5038:   MatGetNonzeroState(mat, &rb->nonzerostate);
5039:   PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB);
5040:   PetscContainerSetPointer(rB, rb);
5041:   PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault);
5042:   PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB);
5043:   PetscObjectDereference((PetscObject)rB);
5044:   return 0;
5045: }

5047: /*@
5048:    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.

5050:    Collective on mat

5052:    Input Parameters:
5053: +  mat - the matrix to transpose
5054: -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`

5056:    Output Parameter:
5057: .  B - the transpose

5059:    Notes:
5060:      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B

5062:      `MAT_REUSE_MATRIX` uses the B matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the
5063:      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.

5065:      If the nonzero structure of mat changed from the previous call to this function with the same matrices an error will be generated for some matrix types.

5067:      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.

5069:      If mat is unchanged from the last call this function returns immediately without recomputing the result

5071:      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`

5073:    Level: intermediate

5075: .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5076:           `MatTransposeSymbolic()`
5077: @*/
5078: PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5079: {
5080:   PetscContainer  rB = NULL;
5081:   MatParentState *rb = NULL;

5089:   MatCheckPreallocated(mat, 1);
5090:   if (reuse == MAT_REUSE_MATRIX) {
5091:     PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5093:     PetscContainerGetPointer(rB, (void **)&rb);
5095:     if (rb->state == ((PetscObject)mat)->state) return 0;
5096:   }

5098:   PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0);
5099:   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5100:     PetscUseTypeMethod(mat, transpose, reuse, B);
5101:     PetscObjectStateIncrease((PetscObject)*B);
5102:   }
5103:   PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0);

5105:   if (reuse == MAT_INITIAL_MATRIX) MatTransposeSetPrecursor(mat, *B);
5106:   if (reuse != MAT_INPLACE_MATRIX) {
5107:     PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5108:     PetscContainerGetPointer(rB, (void **)&rb);
5109:     rb->state        = ((PetscObject)mat)->state;
5110:     rb->nonzerostate = mat->nonzerostate;
5111:   }
5112:   return 0;
5113: }

5115: /*@
5116:    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.

5118:    Collective on A

5120:    Input Parameters:
5121: .  A - the matrix to transpose

5123:    Output Parameter:
5124: .  B - the transpose. This is a complete matrix but the numerical portion is invalid. One can call `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) to compute the
5125:       numerical portion.

5127:    Level: intermediate

5129:    Note:
5130:    This is not supported for many matrix types, use `MatTranspose()` in those cases

5132: .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5133: @*/
5134: PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5135: {
5141:   PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0);
5142:   (*A->ops->transposesymbolic)(A, B);
5143:   PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0);

5145:   MatTransposeSetPrecursor(A, *B);
5146:   return 0;
5147: }

5149: PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5150: {
5151:   PetscContainer  rB;
5152:   MatParentState *rb;

5158:   PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB);
5160:   PetscContainerGetPointer(rB, (void **)&rb);
5163:   return 0;
5164: }

5166: /*@
5167:    MatIsTranspose - Test whether a matrix is another one's transpose,
5168:         or its own, in which case it tests symmetry.

5170:    Collective on A

5172:    Input Parameters:
5173: +  A - the matrix to test
5174: -  B - the matrix to test against, this can equal the first parameter

5176:    Output Parameters:
5177: .  flg - the result

5179:    Notes:
5180:    Only available for `MATAIJ` matrices.

5182:    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5183:    test involves parallel copies of the block-offdiagonal parts of the matrix.

5185:    Level: intermediate

5187: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5188: @*/
5189: PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5190: {
5191:   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);

5196:   PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f);
5197:   PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g);
5198:   *flg = PETSC_FALSE;
5199:   if (f && g) {
5201:     (*f)(A, B, tol, flg);
5202:   } else {
5203:     MatType mattype;

5205:     MatGetType(f ? B : A, &mattype);
5206:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5207:   }
5208:   return 0;
5209: }

5211: /*@
5212:    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.

5214:    Collective on mat

5216:    Input Parameters:
5217: +  mat - the matrix to transpose and complex conjugate
5218: -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`

5220:    Output Parameter:
5221: .  B - the Hermitian transpose

5223:    Level: intermediate

5225: .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5226: @*/
5227: PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5228: {
5229:   MatTranspose(mat, reuse, B);
5230: #if defined(PETSC_USE_COMPLEX)
5231:   MatConjugate(*B);
5232: #endif
5233:   return 0;
5234: }

5236: /*@
5237:    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,

5239:    Collective on A

5241:    Input Parameters:
5242: +  A - the matrix to test
5243: -  B - the matrix to test against, this can equal the first parameter

5245:    Output Parameters:
5246: .  flg - the result

5248:    Notes:
5249:    Only available for `MATAIJ` matrices.

5251:    The sequential algorithm
5252:    has a running time of the order of the number of nonzeros; the parallel
5253:    test involves parallel copies of the block-offdiagonal parts of the matrix.

5255:    Level: intermediate

5257: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5258: @*/
5259: PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5260: {
5261:   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);

5266:   PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f);
5267:   PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g);
5268:   if (f && g) {
5270:     (*f)(A, B, tol, flg);
5271:   }
5272:   return 0;
5273: }

5275: /*@
5276:    MatPermute - Creates a new matrix with rows and columns permuted from the
5277:    original.

5279:    Collective on mat

5281:    Input Parameters:
5282: +  mat - the matrix to permute
5283: .  row - row permutation, each processor supplies only the permutation for its rows
5284: -  col - column permutation, each processor supplies only the permutation for its columns

5286:    Output Parameters:
5287: .  B - the permuted matrix

5289:    Level: advanced

5291:    Note:
5292:    The index sets map from row/col of permuted matrix to row/col of original matrix.
5293:    The index sets should be on the same communicator as mat and have the same local sizes.

5295:    Developer Note:
5296:      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5297:      exploit the fact that row and col are permutations, consider implementing the
5298:      more general `MatCreateSubMatrix()` instead.

5300: .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5301: @*/
5302: PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5303: {
5314:   MatCheckPreallocated(mat, 1);

5316:   if (mat->ops->permute) {
5317:     PetscUseTypeMethod(mat, permute, row, col, B);
5318:     PetscObjectStateIncrease((PetscObject)*B);
5319:   } else {
5320:     MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B);
5321:   }
5322:   return 0;
5323: }

5325: /*@
5326:    MatEqual - Compares two matrices.

5328:    Collective on A

5330:    Input Parameters:
5331: +  A - the first matrix
5332: -  B - the second matrix

5334:    Output Parameter:
5335: .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.

5337:    Level: intermediate

5339: .seealso: `Mat`
5340: @*/
5341: PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5342: {
5349:   MatCheckPreallocated(A, 1);
5350:   MatCheckPreallocated(B, 2);
5354:              B->cmap->N);
5355:   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5356:     PetscUseTypeMethod(A, equal, B, flg);
5357:   } else {
5358:     MatMultEqual(A, B, 10, flg);
5359:   }
5360:   return 0;
5361: }

5363: /*@
5364:    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5365:    matrices that are stored as vectors.  Either of the two scaling
5366:    matrices can be NULL.

5368:    Collective on mat

5370:    Input Parameters:
5371: +  mat - the matrix to be scaled
5372: .  l - the left scaling vector (or NULL)
5373: -  r - the right scaling vector (or NULL)

5375:    Note:
5376:    `MatDiagonalScale()` computes A = LAR, where
5377:    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5378:    The L scales the rows of the matrix, the R scales the columns of the matrix.

5380:    Level: intermediate

5382: .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5383: @*/
5384: PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5385: {
5388:   if (l) {
5391:   }
5392:   if (r) {
5395:   }
5398:   MatCheckPreallocated(mat, 1);
5399:   if (!l && !r) return 0;

5401:   PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5402:   PetscUseTypeMethod(mat, diagonalscale, l, r);
5403:   PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5404:   PetscObjectStateIncrease((PetscObject)mat);
5405:   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5406:   return 0;
5407: }

5409: /*@
5410:     MatScale - Scales all elements of a matrix by a given number.

5412:     Logically Collective on mat

5414:     Input Parameters:
5415: +   mat - the matrix to be scaled
5416: -   a  - the scaling value

5418:     Output Parameter:
5419: .   mat - the scaled matrix

5421:     Level: intermediate

5423: .seealso: `Mat`, `MatDiagonalScale()`
5424: @*/
5425: PetscErrorCode MatScale(Mat mat, PetscScalar a)
5426: {
5433:   MatCheckPreallocated(mat, 1);

5435:   PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5436:   if (a != (PetscScalar)1.0) {
5437:     PetscUseTypeMethod(mat, scale, a);
5438:     PetscObjectStateIncrease((PetscObject)mat);
5439:   }
5440:   PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5441:   return 0;
5442: }

5444: /*@
5445:    MatNorm - Calculates various norms of a matrix.

5447:    Collective on mat

5449:    Input Parameters:
5450: +  mat - the matrix
5451: -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`

5453:    Output Parameter:
5454: .  nrm - the resulting norm

5456:    Level: intermediate

5458: .seealso: `Mat`
5459: @*/
5460: PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5461: {

5468:   MatCheckPreallocated(mat, 1);

5470:   PetscUseTypeMethod(mat, norm, type, nrm);
5471:   return 0;
5472: }

5474: /*
5475:      This variable is used to prevent counting of MatAssemblyBegin() that
5476:    are called from within a MatAssemblyEnd().
5477: */
5478: static PetscInt MatAssemblyEnd_InUse = 0;
5479: /*@
5480:    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5481:    be called after completing all calls to `MatSetValues()`.

5483:    Collective on mat

5485:    Input Parameters:
5486: +  mat - the matrix
5487: -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`

5489:    Notes:
5490:    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5491:    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.

5493:    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5494:    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5495:    using the matrix.

5497:    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5498:    same flag of `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` for all processes. Thus you CANNOT locally change from `ADD_VALUES` to `INSERT_VALUES`, that is
5499:    a global collective operation requring all processes that share the matrix.

5501:    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5502:    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5503:    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.

5505:    Level: beginner

5507: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5508: @*/
5509: PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5510: {
5513:   MatCheckPreallocated(mat, 1);
5515:   if (mat->assembled) {
5516:     mat->was_assembled = PETSC_TRUE;
5517:     mat->assembled     = PETSC_FALSE;
5518:   }

5520:   if (!MatAssemblyEnd_InUse) {
5521:     PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0);
5522:     PetscTryTypeMethod(mat, assemblybegin, type);
5523:     PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0);
5524:   } else PetscTryTypeMethod(mat, assemblybegin, type);
5525:   return 0;
5526: }

5528: /*@
5529:    MatAssembled - Indicates if a matrix has been assembled and is ready for
5530:      use; for example, in matrix-vector product.

5532:    Not Collective

5534:    Input Parameter:
5535: .  mat - the matrix

5537:    Output Parameter:
5538: .  assembled - `PETSC_TRUE` or `PETSC_FALSE`

5540:    Level: advanced

5542: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5543: @*/
5544: PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5545: {
5548:   *assembled = mat->assembled;
5549:   return 0;
5550: }

5552: /*@
5553:    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5554:    be called after `MatAssemblyBegin()`.

5556:    Collective on Mat

5558:    Input Parameters:
5559: +  mat - the matrix
5560: -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`

5562:    Options Database Keys:
5563: +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5564: .  -mat_view ::ascii_info_detail - Prints more detailed info
5565: .  -mat_view - Prints matrix in ASCII format
5566: .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5567: .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5568: .  -display <name> - Sets display name (default is host)
5569: .  -draw_pause <sec> - Sets number of seconds to pause after display
5570: .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5571: .  -viewer_socket_machine <machine> - Machine to use for socket
5572: .  -viewer_socket_port <port> - Port number to use for socket
5573: -  -mat_view binary:filename[:append] - Save matrix to file in binary format

5575:    Level: beginner

5577: .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5578: @*/
5579: PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5580: {
5581:   static PetscInt inassm = 0;
5582:   PetscBool       flg    = PETSC_FALSE;


5587:   inassm++;
5588:   MatAssemblyEnd_InUse++;
5589:   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5590:     PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0);
5591:     PetscTryTypeMethod(mat, assemblyend, type);
5592:     PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0);
5593:   } else PetscTryTypeMethod(mat, assemblyend, type);

5595:   /* Flush assembly is not a true assembly */
5596:   if (type != MAT_FLUSH_ASSEMBLY) {
5597:     if (mat->num_ass) {
5598:       if (!mat->symmetry_eternal) {
5599:         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5600:         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5601:       }
5602:       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5603:       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5604:     }
5605:     mat->num_ass++;
5606:     mat->assembled        = PETSC_TRUE;
5607:     mat->ass_nonzerostate = mat->nonzerostate;
5608:   }

5610:   mat->insertmode = NOT_SET_VALUES;
5611:   MatAssemblyEnd_InUse--;
5612:   PetscObjectStateIncrease((PetscObject)mat);
5613:   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5614:     MatViewFromOptions(mat, NULL, "-mat_view");

5616:     if (mat->checksymmetryonassembly) {
5617:       MatIsSymmetric(mat, mat->checksymmetrytol, &flg);
5618:       if (flg) {
5619:         PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5620:       } else {
5621:         PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5622:       }
5623:     }
5624:     if (mat->nullsp && mat->checknullspaceonassembly) MatNullSpaceTest(mat->nullsp, mat, NULL);
5625:   }
5626:   inassm--;
5627:   return 0;
5628: }

5630: /*@
5631:    MatSetOption - Sets a parameter option for a matrix. Some options
5632:    may be specific to certain storage formats.  Some options
5633:    determine how values will be inserted (or added). Sorted,
5634:    row-oriented input will generally assemble the fastest. The default
5635:    is row-oriented.

5637:    Logically Collective on mat for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`

5639:    Input Parameters:
5640: +  mat - the matrix
5641: .  option - the option, one of those listed below (and possibly others),
5642: -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)

5644:   Options Describing Matrix Structure:
5645: +    `MAT_SPD` - symmetric positive definite
5646: .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5647: .    `MAT_HERMITIAN` - transpose is the complex conjugation
5648: .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5649: .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5650: .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5651: -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix

5653:    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5654:    do not need to be computed (usually at a high cost)

5656:    Options For Use with `MatSetValues()`:
5657:    Insert a logically dense subblock, which can be
5658: .    `MAT_ROW_ORIENTED` - row-oriented (default)

5660:    Note these options reflect the data you pass in with `MatSetValues()`; it has
5661:    nothing to do with how the data is stored internally in the matrix
5662:    data structure.

5664:    When (re)assembling a matrix, we can restrict the input for
5665:    efficiency/debugging purposes.  These options include
5666: +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5667: .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5668: .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5669: .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5670: .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5671: .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5672:         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5673:         performance for very large process counts.
5674: -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5675:         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5676:         functions, instead sending only neighbor messages.

5678:    Notes:
5679:    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!

5681:    Some options are relevant only for particular matrix types and
5682:    are thus ignored by others.  Other options are not supported by
5683:    certain matrix types and will generate an error message if set.

5685:    If using a Fortran 77 module to compute a matrix, one may need to
5686:    use the column-oriented option (or convert to the row-oriented
5687:    format).

5689:    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5690:    that would generate a new entry in the nonzero structure is instead
5691:    ignored.  Thus, if memory has not alredy been allocated for this particular
5692:    data, then the insertion is ignored. For dense matrices, in which
5693:    the entire array is allocated, no entries are ever ignored.
5694:    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction

5696:    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5697:    that would generate a new entry in the nonzero structure instead produces
5698:    an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats only.) If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction

5700:    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5701:    that would generate a new entry that has not been preallocated will
5702:    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5703:    only.) This is a useful flag when debugging matrix memory preallocation.
5704:    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction

5706:    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5707:    other processors should be dropped, rather than stashed.
5708:    This is useful if you know that the "owning" processor is also
5709:    always generating the correct matrix entries, so that PETSc need
5710:    not transfer duplicate entries generated on another processor.

5712:    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5713:    searches during matrix assembly. When this flag is set, the hash table
5714:    is created during the first matrix assembly. This hash table is
5715:    used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5716:    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5717:    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5718:    supported by` MATMPIBAIJ` format only.

5720:    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5721:    are kept in the nonzero structure

5723:    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5724:    a zero location in the matrix

5726:    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types

5728:    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5729:         zero row routines and thus improves performance for very large process counts.

5731:    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5732:         part of the matrix (since they should match the upper triangular part).

5734:    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5735:                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5736:                      with finite difference schemes with non-periodic boundary conditions.

5738:    Developer Note:
5739:    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5740:    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5741:    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5742:    not changed.

5744:    Level: intermediate

5746: .seealso: `MatOption`, `Mat`, `MatGetOption()`
5747: @*/
5748: PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5749: {
5751:   if (op > 0) {
5754:   }


5758:   switch (op) {
5759:   case MAT_FORCE_DIAGONAL_ENTRIES:
5760:     mat->force_diagonals = flg;
5761:     return 0;
5762:   case MAT_NO_OFF_PROC_ENTRIES:
5763:     mat->nooffprocentries = flg;
5764:     return 0;
5765:   case MAT_SUBSET_OFF_PROC_ENTRIES:
5766:     mat->assembly_subset = flg;
5767:     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5768: #if !defined(PETSC_HAVE_MPIUNI)
5769:       MatStashScatterDestroy_BTS(&mat->stash);
5770: #endif
5771:       mat->stash.first_assembly_done = PETSC_FALSE;
5772:     }
5773:     return 0;
5774:   case MAT_NO_OFF_PROC_ZERO_ROWS:
5775:     mat->nooffproczerorows = flg;
5776:     return 0;
5777:   case MAT_SPD:
5778:     if (flg) {
5779:       mat->spd                    = PETSC_BOOL3_TRUE;
5780:       mat->symmetric              = PETSC_BOOL3_TRUE;
5781:       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5782:     } else {
5783:       mat->spd = PETSC_BOOL3_FALSE;
5784:     }
5785:     break;
5786:   case MAT_SYMMETRIC:
5787:     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5788:     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5789: #if !defined(PETSC_USE_COMPLEX)
5790:     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5791: #endif
5792:     break;
5793:   case MAT_HERMITIAN:
5794:     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5795:     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5796: #if !defined(PETSC_USE_COMPLEX)
5797:     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5798: #endif
5799:     break;
5800:   case MAT_STRUCTURALLY_SYMMETRIC:
5801:     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5802:     break;
5803:   case MAT_SYMMETRY_ETERNAL:
5805:     mat->symmetry_eternal = flg;
5806:     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5807:     break;
5808:   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5810:     mat->structural_symmetry_eternal = flg;
5811:     break;
5812:   case MAT_SPD_ETERNAL:
5814:     mat->spd_eternal = flg;
5815:     if (flg) {
5816:       mat->structural_symmetry_eternal = PETSC_TRUE;
5817:       mat->symmetry_eternal            = PETSC_TRUE;
5818:     }
5819:     break;
5820:   case MAT_STRUCTURE_ONLY:
5821:     mat->structure_only = flg;
5822:     break;
5823:   case MAT_SORTED_FULL:
5824:     mat->sortedfull = flg;
5825:     break;
5826:   default:
5827:     break;
5828:   }
5829:   PetscTryTypeMethod(mat, setoption, op, flg);
5830:   return 0;
5831: }

5833: /*@
5834:    MatGetOption - Gets a parameter option that has been set for a matrix.

5836:    Logically Collective on mat

5838:    Input Parameters:
5839: +  mat - the matrix
5840: -  option - the option, this only responds to certain options, check the code for which ones

5842:    Output Parameter:
5843: .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)

5845:     Notes:
5846:     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.

5848:     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5849:     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`

5851:    Level: intermediate

5853: .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5854:     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5855: @*/
5856: PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5857: {


5864:   switch (op) {
5865:   case MAT_NO_OFF_PROC_ENTRIES:
5866:     *flg = mat->nooffprocentries;
5867:     break;
5868:   case MAT_NO_OFF_PROC_ZERO_ROWS:
5869:     *flg = mat->nooffproczerorows;
5870:     break;
5871:   case MAT_SYMMETRIC:
5872:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5873:     break;
5874:   case MAT_HERMITIAN:
5875:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5876:     break;
5877:   case MAT_STRUCTURALLY_SYMMETRIC:
5878:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5879:     break;
5880:   case MAT_SPD:
5881:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
5882:     break;
5883:   case MAT_SYMMETRY_ETERNAL:
5884:     *flg = mat->symmetry_eternal;
5885:     break;
5886:   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5887:     *flg = mat->symmetry_eternal;
5888:     break;
5889:   default:
5890:     break;
5891:   }
5892:   return 0;
5893: }

5895: /*@
5896:    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5897:    this routine retains the old nonzero structure.

5899:    Logically Collective on mat

5901:    Input Parameters:
5902: .  mat - the matrix

5904:    Level: intermediate

5906:    Note:
5907:     If the matrix was not preallocated then a default, likely poor preallocation will be set in the matrix, so this should be called after the preallocation phase.
5908:    See the Performance chapter of the users manual for information on preallocating matrices.

5910: .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
5911: @*/
5912: PetscErrorCode MatZeroEntries(Mat mat)
5913: {
5918:   MatCheckPreallocated(mat, 1);

5920:   PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0);
5921:   PetscUseTypeMethod(mat, zeroentries);
5922:   PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0);
5923:   PetscObjectStateIncrease((PetscObject)mat);
5924:   return 0;
5925: }

5927: /*@
5928:    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5929:    of a set of rows and columns of a matrix.

5931:    Collective on mat

5933:    Input Parameters:
5934: +  mat - the matrix
5935: .  numRows - the number of rows to remove
5936: .  rows - the global row indices
5937: .  diag - value put in the diagonal of the eliminated rows
5938: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5939: -  b - optional vector of right hand side, that will be adjusted by provided solution

5941:    Notes:
5942:    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.

5944:    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5945:    The other entries of b will be adjusted by the known values of x times the corresponding matrix entries in the columns that are being eliminated

5947:    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5948:    Krylov method to take advantage of the known solution on the zeroed rows.

5950:    For the parallel case, all processes that share the matrix (i.e.,
5951:    those in the communicator used for matrix creation) MUST call this
5952:    routine, regardless of whether any rows being zeroed are owned by
5953:    them.

5955:    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.

5957:    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5958:    list only rows local to itself).

5960:    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.

5962:    Level: intermediate

5964: .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5965:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5966: @*/
5967: PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
5968: {
5974:   MatCheckPreallocated(mat, 1);

5976:   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
5977:   MatViewFromOptions(mat, NULL, "-mat_view");
5978:   PetscObjectStateIncrease((PetscObject)mat);
5979:   return 0;
5980: }

5982: /*@
5983:    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5984:    of a set of rows and columns of a matrix.

5986:    Collective on mat

5988:    Input Parameters:
5989: +  mat - the matrix
5990: .  is - the rows to zero
5991: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5992: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5993: -  b - optional vector of right hand side, that will be adjusted by provided solution

5995:    Note:
5996:    See `MatZeroRowsColumns()` for details on how this routine operates.

5998:    Level: intermediate

6000: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6001:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6002: @*/
6003: PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6004: {
6005:   PetscInt        numRows;
6006:   const PetscInt *rows;

6012:   ISGetLocalSize(is, &numRows);
6013:   ISGetIndices(is, &rows);
6014:   MatZeroRowsColumns(mat, numRows, rows, diag, x, b);
6015:   ISRestoreIndices(is, &rows);
6016:   return 0;
6017: }

6019: /*@
6020:    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6021:    of a set of rows of a matrix.

6023:    Collective on mat

6025:    Input Parameters:
6026: +  mat - the matrix
6027: .  numRows - the number of rows to remove
6028: .  rows - the global row indices
6029: .  diag - value put in the diagonal of the eliminated rows
6030: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6031: -  b - optional vector of right hand side, that will be adjusted by provided solution

6033:    Notes:
6034:    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.

6036:    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.

6038:    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6039:    Krylov method to take advantage of the known solution on the zeroed rows.

6041:    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reducing problem (after completely eliminating the zeroed rows and their corresponding columns)
6042:    from the matrix.

6044:    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6045:    but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal
6046:    formats this does not alter the nonzero structure.

6048:    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6049:    of the matrix is not changed the values are
6050:    merely zeroed.

6052:    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6053:    formats can optionally remove the main diagonal entry from the
6054:    nonzero structure as well, by passing 0.0 as the final argument).

6056:    For the parallel case, all processes that share the matrix (i.e.,
6057:    those in the communicator used for matrix creation) MUST call this
6058:    routine, regardless of whether any rows being zeroed are owned by
6059:    them.

6061:    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6062:    list only rows local to itself).

6064:    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6065:    owns that are to be zeroed. This saves a global synchronization in the implementation.

6067:    Level: intermediate

6069: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6070:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6071: @*/
6072: PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6073: {
6079:   MatCheckPreallocated(mat, 1);

6081:   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6082:   MatViewFromOptions(mat, NULL, "-mat_view");
6083:   PetscObjectStateIncrease((PetscObject)mat);
6084:   return 0;
6085: }

6087: /*@
6088:    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6089:    of a set of rows of a matrix.

6091:    Collective on Mat

6093:    Input Parameters:
6094: +  mat - the matrix
6095: .  is - index set of rows to remove (if NULL then no row is removed)
6096: .  diag - value put in all diagonals of eliminated rows
6097: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6098: -  b - optional vector of right hand side, that will be adjusted by provided solution

6100:    Note:
6101:    See `MatZeroRows()` for details on how this routine operates.

6103:    Level: intermediate

6105: .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6106:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6107: @*/
6108: PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6109: {
6110:   PetscInt        numRows = 0;
6111:   const PetscInt *rows    = NULL;

6115:   if (is) {
6117:     ISGetLocalSize(is, &numRows);
6118:     ISGetIndices(is, &rows);
6119:   }
6120:   MatZeroRows(mat, numRows, rows, diag, x, b);
6121:   if (is) ISRestoreIndices(is, &rows);
6122:   return 0;
6123: }

6125: /*@
6126:    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6127:    of a set of rows of a matrix. These rows must be local to the process.

6129:    Collective on mat

6131:    Input Parameters:
6132: +  mat - the matrix
6133: .  numRows - the number of rows to remove
6134: .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6135: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6136: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6137: -  b - optional vector of right hand side, that will be adjusted by provided solution

6139:    Notes:
6140:    See `MatZeroRows()` for details on how this routine operates.

6142:    The grid coordinates are across the entire grid, not just the local portion

6144:    In Fortran idxm and idxn should be declared as
6145: $     MatStencil idxm(4,m)
6146:    and the values inserted using
6147: $    idxm(MatStencil_i,1) = i
6148: $    idxm(MatStencil_j,1) = j
6149: $    idxm(MatStencil_k,1) = k
6150: $    idxm(MatStencil_c,1) = c
6151:    etc

6153:    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6154:    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6155:    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6156:    `DM_BOUNDARY_PERIODIC` boundary type.

6158:    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
6159:    a single value per point) you can skip filling those indices.

6161:    Level: intermediate

6163: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6164:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6165: @*/
6166: PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6167: {
6168:   PetscInt  dim    = mat->stencil.dim;
6169:   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6170:   PetscInt *dims   = mat->stencil.dims + 1;
6171:   PetscInt *starts = mat->stencil.starts;
6172:   PetscInt *dxm    = (PetscInt *)rows;
6173:   PetscInt *jdxm, i, j, tmp, numNewRows = 0;


6179:   PetscMalloc1(numRows, &jdxm);
6180:   for (i = 0; i < numRows; ++i) {
6181:     /* Skip unused dimensions (they are ordered k, j, i, c) */
6182:     for (j = 0; j < 3 - sdim; ++j) dxm++;
6183:     /* Local index in X dir */
6184:     tmp = *dxm++ - starts[0];
6185:     /* Loop over remaining dimensions */
6186:     for (j = 0; j < dim - 1; ++j) {
6187:       /* If nonlocal, set index to be negative */
6188:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6189:       /* Update local index */
6190:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6191:     }
6192:     /* Skip component slot if necessary */
6193:     if (mat->stencil.noc) dxm++;
6194:     /* Local row number */
6195:     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6196:   }
6197:   MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b);
6198:   PetscFree(jdxm);
6199:   return 0;
6200: }

6202: /*@
6203:    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6204:    of a set of rows and columns of a matrix.

6206:    Collective on mat

6208:    Input Parameters:
6209: +  mat - the matrix
6210: .  numRows - the number of rows/columns to remove
6211: .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6212: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6213: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6214: -  b - optional vector of right hand side, that will be adjusted by provided solution

6216:    Notes:
6217:    See `MatZeroRowsColumns()` for details on how this routine operates.

6219:    The grid coordinates are across the entire grid, not just the local portion

6221:    In Fortran idxm and idxn should be declared as
6222: $     MatStencil idxm(4,m)
6223:    and the values inserted using
6224: $    idxm(MatStencil_i,1) = i
6225: $    idxm(MatStencil_j,1) = j
6226: $    idxm(MatStencil_k,1) = k
6227: $    idxm(MatStencil_c,1) = c
6228:    etc

6230:    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6231:    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6232:    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6233:    `DM_BOUNDARY_PERIODIC` boundary type.

6235:    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
6236:    a single value per point) you can skip filling those indices.

6238:    Level: intermediate

6240: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6241:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6242: @*/
6243: PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6244: {
6245:   PetscInt  dim    = mat->stencil.dim;
6246:   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6247:   PetscInt *dims   = mat->stencil.dims + 1;
6248:   PetscInt *starts = mat->stencil.starts;
6249:   PetscInt *dxm    = (PetscInt *)rows;
6250:   PetscInt *jdxm, i, j, tmp, numNewRows = 0;


6256:   PetscMalloc1(numRows, &jdxm);
6257:   for (i = 0; i < numRows; ++i) {
6258:     /* Skip unused dimensions (they are ordered k, j, i, c) */
6259:     for (j = 0; j < 3 - sdim; ++j) dxm++;
6260:     /* Local index in X dir */
6261:     tmp = *dxm++ - starts[0];
6262:     /* Loop over remaining dimensions */
6263:     for (j = 0; j < dim - 1; ++j) {
6264:       /* If nonlocal, set index to be negative */
6265:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6266:       /* Update local index */
6267:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6268:     }
6269:     /* Skip component slot if necessary */
6270:     if (mat->stencil.noc) dxm++;
6271:     /* Local row number */
6272:     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6273:   }
6274:   MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b);
6275:   PetscFree(jdxm);
6276:   return 0;
6277: }

6279: /*@C
6280:    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6281:    of a set of rows of a matrix; using local numbering of rows.

6283:    Collective on mat

6285:    Input Parameters:
6286: +  mat - the matrix
6287: .  numRows - the number of rows to remove
6288: .  rows - the local row indices
6289: .  diag - value put in all diagonals of eliminated rows
6290: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6291: -  b - optional vector of right hand side, that will be adjusted by provided solution

6293:    Notes:
6294:    Before calling `MatZeroRowsLocal()`, the user must first set the
6295:    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.

6297:    See `MatZeroRows()` for details on how this routine operates.

6299:    Level: intermediate

6301: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6302:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6303: @*/
6304: PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6305: {
6311:   MatCheckPreallocated(mat, 1);

6313:   if (mat->ops->zerorowslocal) {
6314:     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6315:   } else {
6316:     IS              is, newis;
6317:     const PetscInt *newRows;

6320:     ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6321:     ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis);
6322:     ISGetIndices(newis, &newRows);
6323:     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6324:     ISRestoreIndices(newis, &newRows);
6325:     ISDestroy(&newis);
6326:     ISDestroy(&is);
6327:   }
6328:   PetscObjectStateIncrease((PetscObject)mat);
6329:   return 0;
6330: }

6332: /*@
6333:    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6334:    of a set of rows of a matrix; using local numbering of rows.

6336:    Collective on mat

6338:    Input Parameters:
6339: +  mat - the matrix
6340: .  is - index set of rows to remove
6341: .  diag - value put in all diagonals of eliminated rows
6342: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6343: -  b - optional vector of right hand side, that will be adjusted by provided solution

6345:    Notes:
6346:    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6347:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6349:    See `MatZeroRows()` for details on how this routine operates.

6351:    Level: intermediate

6353: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6354:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6355: @*/
6356: PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6357: {
6358:   PetscInt        numRows;
6359:   const PetscInt *rows;

6366:   MatCheckPreallocated(mat, 1);

6368:   ISGetLocalSize(is, &numRows);
6369:   ISGetIndices(is, &rows);
6370:   MatZeroRowsLocal(mat, numRows, rows, diag, x, b);
6371:   ISRestoreIndices(is, &rows);
6372:   return 0;
6373: }

6375: /*@
6376:    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6377:    of a set of rows and columns of a matrix; using local numbering of rows.

6379:    Collective on mat

6381:    Input Parameters:
6382: +  mat - the matrix
6383: .  numRows - the number of rows to remove
6384: .  rows - the global row indices
6385: .  diag - value put in all diagonals of eliminated rows
6386: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6387: -  b - optional vector of right hand side, that will be adjusted by provided solution

6389:    Notes:
6390:    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6391:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6393:    See `MatZeroRowsColumns()` for details on how this routine operates.

6395:    Level: intermediate

6397: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6398:           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6399: @*/
6400: PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6401: {
6402:   IS              is, newis;
6403:   const PetscInt *newRows;

6410:   MatCheckPreallocated(mat, 1);

6413:   ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6414:   ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis);
6415:   ISGetIndices(newis, &newRows);
6416:   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6417:   ISRestoreIndices(newis, &newRows);
6418:   ISDestroy(&newis);
6419:   ISDestroy(&is);
6420:   PetscObjectStateIncrease((PetscObject)mat);
6421:   return 0;
6422: }

6424: /*@
6425:    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6426:    of a set of rows and columns of a matrix; using local numbering of rows.

6428:    Collective on Mat

6430:    Input Parameters:
6431: +  mat - the matrix
6432: .  is - index set of rows to remove
6433: .  diag - value put in all diagonals of eliminated rows
6434: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6435: -  b - optional vector of right hand side, that will be adjusted by provided solution

6437:    Notes:
6438:    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6439:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6441:    See `MatZeroRowsColumns()` for details on how this routine operates.

6443:    Level: intermediate

6445: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6446:           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6447: @*/
6448: PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6449: {
6450:   PetscInt        numRows;
6451:   const PetscInt *rows;

6458:   MatCheckPreallocated(mat, 1);

6460:   ISGetLocalSize(is, &numRows);
6461:   ISGetIndices(is, &rows);
6462:   MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b);
6463:   ISRestoreIndices(is, &rows);
6464:   return 0;
6465: }

6467: /*@C
6468:    MatGetSize - Returns the numbers of rows and columns in a matrix.

6470:    Not Collective

6472:    Input Parameter:
6473: .  mat - the matrix

6475:    Output Parameters:
6476: +  m - the number of global rows
6477: -  n - the number of global columns

6479:    Note: both output parameters can be NULL on input.

6481:    Level: beginner

6483: .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6484: @*/
6485: PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6486: {
6488:   if (m) *m = mat->rmap->N;
6489:   if (n) *n = mat->cmap->N;
6490:   return 0;
6491: }

6493: /*@C
6494:    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6495:    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.

6497:    Not Collective

6499:    Input Parameter:
6500: .  mat - the matrix

6502:    Output Parameters:
6503: +  m - the number of local rows, use `NULL` to not obtain this value
6504: -  n - the number of local columns, use `NULL` to not obtain this value

6506:    Level: beginner

6508: .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6509: @*/
6510: PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6511: {
6515:   if (m) *m = mat->rmap->n;
6516:   if (n) *n = mat->cmap->n;
6517:   return 0;
6518: }

6520: /*@C
6521:    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6522:    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.

6524:    Not Collective, unless matrix has not been allocated, then collective on mat

6526:    Input Parameter:
6527: .  mat - the matrix

6529:    Output Parameters:
6530: +  m - the global index of the first local column, use `NULL` to not obtain this value
6531: -  n - one more than the global index of the last local column, use `NULL` to not obtain this value

6533:    Level: developer

6535: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6536: @*/
6537: PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6538: {
6543:   MatCheckPreallocated(mat, 1);
6544:   if (m) *m = mat->cmap->rstart;
6545:   if (n) *n = mat->cmap->rend;
6546:   return 0;
6547: }

6549: /*@C
6550:    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6551:    this MPI rank. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6552:    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts

6554:    Not Collective

6556:    Input Parameter:
6557: .  mat - the matrix

6559:    Output Parameters:
6560: +  m - the global index of the first local row, use `NULL` to not obtain this value
6561: -  n - one more than the global index of the last local row, use `NULL` to not obtain this value

6563:    Note:
6564:   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6565:   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6566:   and then `MPI_Scan()` to calculate prefix sums of the local sizes.

6568:    Level: beginner

6570: .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6571:           `PetscLayout`
6572: @*/
6573: PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6574: {
6579:   MatCheckPreallocated(mat, 1);
6580:   if (m) *m = mat->rmap->rstart;
6581:   if (n) *n = mat->rmap->rend;
6582:   return 0;
6583: }

6585: /*@C
6586:    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6587:    each process. For all matrices  it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix
6588:    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts

6590:    Not Collective, unless matrix has not been allocated, then collective on mat

6592:    Input Parameters:
6593: .  mat - the matrix

6595:    Output Parameters:
6596: .  ranges - start of each processors portion plus one more than the total length at the end

6598:    Level: beginner

6600: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6601: @*/
6602: PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6603: {
6606:   MatCheckPreallocated(mat, 1);
6607:   PetscLayoutGetRanges(mat->rmap, ranges);
6608:   return 0;
6609: }

6611: /*@C
6612:    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6613:    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.

6615:    Not Collective, unless matrix has not been allocated, then collective on Mat

6617:    Input Parameters:
6618: .  mat - the matrix

6620:    Output Parameters:
6621: .  ranges - start of each processors portion plus one more then the total length at the end

6623:    Level: beginner

6625: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6626: @*/
6627: PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6628: {
6631:   MatCheckPreallocated(mat, 1);
6632:   PetscLayoutGetRanges(mat->cmap, ranges);
6633:   return 0;
6634: }

6636: /*@C
6637:    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6638:    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6639:    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.

6641:    Not Collective

6643:    Input Parameter:
6644: .  A - matrix

6646:    Output Parameters:
6647: +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6648: -  cols - columns in which this process owns elements, use `NULL` to not obtain this value

6650:    Level: intermediate

6652: .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6653: @*/
6654: PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6655: {
6656:   PetscErrorCode (*f)(Mat, IS *, IS *);

6658:   MatCheckPreallocated(A, 1);
6659:   PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f);
6660:   if (f) {
6661:     (*f)(A, rows, cols);
6662:   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6663:     if (rows) ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows);
6664:     if (cols) ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols);
6665:   }
6666:   return 0;
6667: }

6669: /*@C
6670:    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6671:    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6672:    to complete the factorization.

6674:    Collective on fact

6676:    Input Parameters:
6677: +  fact - the factorized matrix obtained with `MatGetFactor()`
6678: .  mat - the matrix
6679: .  row - row permutation
6680: .  column - column permutation
6681: -  info - structure containing
6682: $      levels - number of levels of fill.
6683: $      expected fill - as ratio of original fill.
6684: $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6685:                 missing diagonal entries)

6687:    Output Parameters:
6688: .  fact - new matrix that has been symbolically factored

6690:    Level: developer

6692:    Notes:
6693:    See [Matrix Factorization](sec_matfactor) for additional information.

6695:    Most users should employ the `KSP` interface for linear solvers
6696:    instead of working directly with matrix algebra routines such as this.
6697:    See, e.g., `KSPCreate()`.

6699:    Uses the definition of level of fill as in Y. Saad, 2003

6701:    Developer Note:
6702:    The Fortran interface is not autogenerated as the f90
6703:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

6705:    References:
6706: .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003

6708: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6709:           `MatGetOrdering()`, `MatFactorInfo`
6710: @*/
6711: PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6712: {
6721:   if (!fact->ops->ilufactorsymbolic) {
6722:     MatSolverType stype;
6723:     MatFactorGetSolverType(fact, &stype);
6724:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6725:   }
6728:   MatCheckPreallocated(mat, 2);

6730:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0);
6731:   (fact->ops->ilufactorsymbolic)(fact, mat, row, col, info);
6732:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0);
6733:   return 0;
6734: }

6736: /*@C
6737:    MatICCFactorSymbolic - Performs symbolic incomplete
6738:    Cholesky factorization for a symmetric matrix.  Use
6739:    `MatCholeskyFactorNumeric()` to complete the factorization.

6741:    Collective on fact

6743:    Input Parameters:
6744: +  fact - the factorized matrix obtained with `MatGetFactor()`
6745: .  mat - the matrix to be factored
6746: .  perm - row and column permutation
6747: -  info - structure containing
6748: $      levels - number of levels of fill.
6749: $      expected fill - as ratio of original fill.

6751:    Output Parameter:
6752: .  fact - the factored matrix

6754:    Level: developer

6756:    Notes:
6757:    Most users should employ the `KSP` interface for linear solvers
6758:    instead of working directly with matrix algebra routines such as this.
6759:    See, e.g., `KSPCreate()`.

6761:    This uses the definition of level of fill as in Y. Saad, 2003

6763:    Developer Note:
6764:    The Fortran interface is not autogenerated as the f90
6765:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

6767:    References:
6768: .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003

6770: .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6771: @*/
6772: PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6773: {
6782:   if (!(fact)->ops->iccfactorsymbolic) {
6783:     MatSolverType stype;
6784:     MatFactorGetSolverType(fact, &stype);
6785:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6786:   }
6788:   MatCheckPreallocated(mat, 2);

6790:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6791:   (fact->ops->iccfactorsymbolic)(fact, mat, perm, info);
6792:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6793:   return 0;
6794: }

6796: /*@C
6797:    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6798:    points to an array of valid matrices, they may be reused to store the new
6799:    submatrices.

6801:    Collective on mat

6803:    Input Parameters:
6804: +  mat - the matrix
6805: .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6806: .  irow, icol - index sets of rows and columns to extract
6807: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

6809:    Output Parameter:
6810: .  submat - the array of submatrices

6812:    Notes:
6813:    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6814:    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6815:    to extract a parallel submatrix.

6817:    Some matrix types place restrictions on the row and column
6818:    indices, such as that they be sorted or that they be equal to each other.

6820:    The index sets may not have duplicate entries.

6822:    When extracting submatrices from a parallel matrix, each processor can
6823:    form a different submatrix by setting the rows and columns of its
6824:    individual index sets according to the local submatrix desired.

6826:    When finished using the submatrices, the user should destroy
6827:    them with `MatDestroySubMatrices()`.

6829:    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6830:    original matrix has not changed from that last call to `MatCreateSubMatrices()`.

6832:    This routine creates the matrices in submat; you should NOT create them before
6833:    calling it. It also allocates the array of matrix pointers submat.

6835:    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6836:    request one row/column in a block, they must request all rows/columns that are in
6837:    that block. For example, if the block size is 2 you cannot request just row 0 and
6838:    column 0.

6840:    Fortran Note:
6841:    The Fortran interface is slightly different from that given below; it
6842:    requires one to pass in  as submat a `Mat` (integer) array of size at least n+1.

6844:    Level: advanced

6846: .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6847: @*/
6848: PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6849: {
6850:   PetscInt  i;
6851:   PetscBool eq;

6855:   if (n) {
6860:   }
6862:   if (n && scall == MAT_REUSE_MATRIX) {
6865:   }
6868:   MatCheckPreallocated(mat, 1);
6869:   PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6870:   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6871:   PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6872:   for (i = 0; i < n; i++) {
6873:     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6874:     ISEqualUnsorted(irow[i], icol[i], &eq);
6875:     if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6876: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
6877:     if (mat->boundtocpu && mat->bindingpropagates) {
6878:       MatBindToCPU((*submat)[i], PETSC_TRUE);
6879:       MatSetBindingPropagates((*submat)[i], PETSC_TRUE);
6880:     }
6881: #endif
6882:   }
6883:   return 0;
6884: }

6886: /*@C
6887:    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).

6889:    Collective on mat

6891:    Input Parameters:
6892: +  mat - the matrix
6893: .  n   - the number of submatrixes to be extracted
6894: .  irow, icol - index sets of rows and columns to extract
6895: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

6897:    Output Parameter:
6898: .  submat - the array of submatrices

6900:    Level: advanced

6902:    Note:
6903:    This is used by `PCGASM`

6905: .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6906: @*/
6907: PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6908: {
6909:   PetscInt  i;
6910:   PetscBool eq;

6914:   if (n) {
6919:   }
6921:   if (n && scall == MAT_REUSE_MATRIX) {
6924:   }
6927:   MatCheckPreallocated(mat, 1);

6929:   PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6930:   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6931:   PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6932:   for (i = 0; i < n; i++) {
6933:     ISEqualUnsorted(irow[i], icol[i], &eq);
6934:     if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6935:   }
6936:   return 0;
6937: }

6939: /*@C
6940:    MatDestroyMatrices - Destroys an array of matrices.

6942:    Collective on mat

6944:    Input Parameters:
6945: +  n - the number of local matrices
6946: -  mat - the matrices (note that this is a pointer to the array of matrices)

6948:    Level: advanced

6950:     Note:
6951:     Frees not only the matrices, but also the array that contains the matrices
6952:            In Fortran will not free the array.

6954: .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6955: @*/
6956: PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
6957: {
6958:   PetscInt i;

6960:   if (!*mat) return 0;

6964:   for (i = 0; i < n; i++) MatDestroy(&(*mat)[i]);

6966:   /* memory is allocated even if n = 0 */
6967:   PetscFree(*mat);
6968:   return 0;
6969: }

6971: /*@C
6972:    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.

6974:    Collective on mat

6976:    Input Parameters:
6977: +  n - the number of local matrices
6978: -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
6979:                        sequence of MatCreateSubMatrices())

6981:    Level: advanced

6983:     Note:
6984:     Frees not only the matrices, but also the array that contains the matrices
6985:            In Fortran will not free the array.

6987: .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6988: @*/
6989: PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
6990: {
6991:   Mat mat0;

6993:   if (!*mat) return 0;
6994:   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */

6998:   mat0 = (*mat)[0];
6999:   if (mat0 && mat0->ops->destroysubmatrices) {
7000:     (mat0->ops->destroysubmatrices)(n, mat);
7001:   } else {
7002:     MatDestroyMatrices(n, mat);
7003:   }
7004:   return 0;
7005: }

7007: /*@C
7008:    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process

7010:    Collective on mat

7012:    Input Parameters:
7013: .  mat - the matrix

7015:    Output Parameter:
7016: .  matstruct - the sequential matrix with the nonzero structure of mat

7018:   Level: developer

7020: .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7021: @*/
7022: PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7023: {

7029:   MatCheckPreallocated(mat, 1);

7031:   PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7032:   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7033:   PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7034:   return 0;
7035: }

7037: /*@C
7038:    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.

7040:    Collective on mat

7042:    Input Parameters:
7043: .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7044:                        sequence of `MatGetSequentialNonzeroStructure()`)

7046:    Level: advanced

7048:     Note:
7049:     Frees not only the matrices, but also the array that contains the matrices

7051: .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7052: @*/
7053: PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7054: {
7056:   MatDestroy(mat);
7057:   return 0;
7058: }

7060: /*@
7061:    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7062:    replaces the index sets by larger ones that represent submatrices with
7063:    additional overlap.

7065:    Collective on mat

7067:    Input Parameters:
7068: +  mat - the matrix
7069: .  n   - the number of index sets
7070: .  is  - the array of index sets (these index sets will changed during the call)
7071: -  ov  - the additional overlap requested

7073:    Options Database:
7074: .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)

7076:    Level: developer

7078:    Developer Note:
7079:    Any implementation must preserve block sizes. That is: if the row block size and the column block size of mat are equal to bs, then the output index sets must be compatible with bs.

7081: .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7082: @*/
7083: PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7084: {
7085:   PetscInt i, bs, cbs;

7091:   if (n) {
7094:   }
7097:   MatCheckPreallocated(mat, 1);

7099:   if (!ov || !n) return 0;
7100:   PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7101:   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7102:   PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7103:   MatGetBlockSizes(mat, &bs, &cbs);
7104:   if (bs == cbs) {
7105:     for (i = 0; i < n; i++) ISSetBlockSize(is[i], bs);
7106:   }
7107:   return 0;
7108: }

7110: PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);

7112: /*@
7113:    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7114:    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7115:    additional overlap.

7117:    Collective on mat

7119:    Input Parameters:
7120: +  mat - the matrix
7121: .  n   - the number of index sets
7122: .  is  - the array of index sets (these index sets will changed during the call)
7123: -  ov  - the additional overlap requested

7125: `   Options Database:
7126: .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)

7128:    Level: developer

7130: .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7131: @*/
7132: PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7133: {
7134:   PetscInt i;

7139:   if (n) {
7142:   }
7145:   MatCheckPreallocated(mat, 1);
7146:   if (!ov) return 0;
7147:   PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7148:   for (i = 0; i < n; i++) MatIncreaseOverlapSplit_Single(mat, &is[i], ov);
7149:   PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7150:   return 0;
7151: }

7153: /*@
7154:    MatGetBlockSize - Returns the matrix block size.

7156:    Not Collective

7158:    Input Parameter:
7159: .  mat - the matrix

7161:    Output Parameter:
7162: .  bs - block size

7164:    Notes:
7165:     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.

7167:    If the block size has not been set yet this routine returns 1.

7169:    Level: intermediate

7171: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7172: @*/
7173: PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7174: {
7177:   *bs = PetscAbs(mat->rmap->bs);
7178:   return 0;
7179: }

7181: /*@
7182:    MatGetBlockSizes - Returns the matrix block row and column sizes.

7184:    Not Collective

7186:    Input Parameter:
7187: .  mat - the matrix

7189:    Output Parameters:
7190: +  rbs - row block size
7191: -  cbs - column block size

7193:    Notes:
7194:     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7195:     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.

7197:    If a block size has not been set yet this routine returns 1.

7199:    Level: intermediate

7201: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7202: @*/
7203: PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7204: {
7208:   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7209:   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7210:   return 0;
7211: }

7213: /*@
7214:    MatSetBlockSize - Sets the matrix block size.

7216:    Logically Collective on mat

7218:    Input Parameters:
7219: +  mat - the matrix
7220: -  bs - block size

7222:    Notes:
7223:     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7224:     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.

7226:     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7227:     is compatible with the matrix local sizes.

7229:    Level: intermediate

7231: .seealso:  `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7232: @*/
7233: PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7234: {
7237:   MatSetBlockSizes(mat, bs, bs);
7238:   return 0;
7239: }

7241: typedef struct {
7242:   PetscInt         n;
7243:   IS              *is;
7244:   Mat             *mat;
7245:   PetscObjectState nonzerostate;
7246:   Mat              C;
7247: } EnvelopeData;

7249: static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7250: {
7251:   for (PetscInt i = 0; i < edata->n; i++) ISDestroy(&edata->is[i]);
7252:   PetscFree(edata->is);
7253:   PetscFree(edata);
7254:   return 0;
7255: }

7257: /*
7258:    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7259:          the sizes of these blocks in the matrix. An individual block may lie over several processes.

7261:    Collective on mat

7263:    Input Parameter:
7264: .  mat - the matrix

7266:    Notes:
7267:      There can be zeros within the blocks

7269:      The blocks can overlap between processes, including laying on more than two processes

7271: .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7272: */
7273: static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7274: {
7275:   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7276:   PetscInt          *diag, *odiag, sc;
7277:   VecScatter         scatter;
7278:   PetscScalar       *seqv;
7279:   const PetscScalar *parv;
7280:   const PetscInt    *ia, *ja;
7281:   PetscBool          set, flag, done;
7282:   Mat                AA = mat, A;
7283:   MPI_Comm           comm;
7284:   PetscMPIInt        rank, size, tag;
7285:   MPI_Status         status;
7286:   PetscContainer     container;
7287:   EnvelopeData      *edata;
7288:   Vec                seq, par;
7289:   IS                 isglobal;

7292:   MatIsSymmetricKnown(mat, &set, &flag);
7293:   if (!set || !flag) {
7294:     /* TOO: only needs nonzero structure of transpose */
7295:     MatTranspose(mat, MAT_INITIAL_MATRIX, &AA);
7296:     MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN);
7297:   }
7298:   MatAIJGetLocalMat(AA, &A);
7299:   MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);

7302:   MatGetLocalSize(mat, &n, NULL);
7303:   PetscObjectGetNewTag((PetscObject)mat, &tag);
7304:   PetscObjectGetComm((PetscObject)mat, &comm);
7305:   MPI_Comm_size(comm, &size);
7306:   MPI_Comm_rank(comm, &rank);

7308:   PetscMalloc2(n, &sizes, n, &starts);

7310:   if (rank > 0) {
7311:     MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status);
7312:     MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status);
7313:   }
7314:   MatGetOwnershipRange(mat, &rstart, NULL);
7315:   for (i = 0; i < n; i++) {
7316:     env = PetscMax(env, ja[ia[i + 1] - 1]);
7317:     II  = rstart + i;
7318:     if (env == II) {
7319:       starts[lblocks]  = tbs;
7320:       sizes[lblocks++] = 1 + II - tbs;
7321:       tbs              = 1 + II;
7322:     }
7323:   }
7324:   if (rank < size - 1) {
7325:     MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm);
7326:     MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm);
7327:   }

7329:   MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7330:   if (!set || !flag) MatDestroy(&AA);
7331:   MatDestroy(&A);

7333:   PetscNew(&edata);
7334:   MatGetNonzeroState(mat, &edata->nonzerostate);
7335:   edata->n = lblocks;
7336:   /* create IS needed for extracting blocks from the original matrix */
7337:   PetscMalloc1(lblocks, &edata->is);
7338:   for (PetscInt i = 0; i < lblocks; i++) ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]);

7340:   /* Create the resulting inverse matrix structure with preallocation information */
7341:   MatCreate(PetscObjectComm((PetscObject)mat), &edata->C);
7342:   MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
7343:   MatSetBlockSizesFromMats(edata->C, mat, mat);
7344:   MatSetType(edata->C, MATAIJ);

7346:   /* Communicate the start and end of each row, from each block to the correct rank */
7347:   /* TODO: Use PetscSF instead of VecScatter */
7348:   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7349:   VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq);
7350:   VecGetArrayWrite(seq, &seqv);
7351:   for (PetscInt i = 0; i < lblocks; i++) {
7352:     for (PetscInt j = 0; j < sizes[i]; j++) {
7353:       seqv[cnt]     = starts[i];
7354:       seqv[cnt + 1] = starts[i] + sizes[i];
7355:       cnt += 2;
7356:     }
7357:   }
7358:   VecRestoreArrayWrite(seq, &seqv);
7359:   MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
7360:   sc -= cnt;
7361:   VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par);
7362:   ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal);
7363:   VecScatterCreate(seq, NULL, par, isglobal, &scatter);
7364:   ISDestroy(&isglobal);
7365:   VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7366:   VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7367:   VecScatterDestroy(&scatter);
7368:   VecDestroy(&seq);
7369:   MatGetOwnershipRangeColumn(mat, &cstart, &cend);
7370:   PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag);
7371:   VecGetArrayRead(par, &parv);
7372:   cnt = 0;
7373:   MatGetSize(mat, NULL, &n);
7374:   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7375:     PetscInt start, end, d = 0, od = 0;

7377:     start = (PetscInt)PetscRealPart(parv[cnt]);
7378:     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7379:     cnt += 2;

7381:     if (start < cstart) {
7382:       od += cstart - start + n - cend;
7383:       d += cend - cstart;
7384:     } else if (start < cend) {
7385:       od += n - cend;
7386:       d += cend - start;
7387:     } else od += n - start;
7388:     if (end <= cstart) {
7389:       od -= cstart - end + n - cend;
7390:       d -= cend - cstart;
7391:     } else if (end < cend) {
7392:       od -= n - cend;
7393:       d -= cend - end;
7394:     } else od -= n - end;

7396:     odiag[i] = od;
7397:     diag[i]  = d;
7398:   }
7399:   VecRestoreArrayRead(par, &parv);
7400:   VecDestroy(&par);
7401:   MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL);
7402:   PetscFree2(diag, odiag);
7403:   PetscFree2(sizes, starts);

7405:   PetscContainerCreate(PETSC_COMM_SELF, &container);
7406:   PetscContainerSetPointer(container, edata);
7407:   PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy);
7408:   PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container);
7409:   PetscObjectDereference((PetscObject)container);
7410:   return 0;
7411: }

7413: /*@
7414:   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A

7416:   Collective on A

7418:   Input Parameters:
7419: . A - the matrix

7421:   Output Parameters:
7422: . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.

7424:   Note:
7425:      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.

7427:   Level: advanced

7429: .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7430: @*/
7431: PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7432: {
7433:   PetscContainer   container;
7434:   EnvelopeData    *edata;
7435:   PetscObjectState nonzerostate;

7437:   PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7438:   if (!container) {
7439:     MatComputeVariableBlockEnvelope(A);
7440:     PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7441:   }
7442:   PetscContainerGetPointer(container, (void **)&edata);
7443:   MatGetNonzeroState(A, &nonzerostate);

7447:   MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat);
7448:   *C = edata->C;

7450:   for (PetscInt i = 0; i < edata->n; i++) {
7451:     Mat          D;
7452:     PetscScalar *dvalues;

7454:     MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D);
7455:     MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE);
7456:     MatSeqDenseInvert(D);
7457:     MatDenseGetArray(D, &dvalues);
7458:     MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES);
7459:     MatDestroy(&D);
7460:   }
7461:   MatDestroySubMatrices(edata->n, &edata->mat);
7462:   MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY);
7463:   MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY);
7464:   return 0;
7465: }

7467: /*@
7468:    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size

7470:    Logically Collective on mat

7472:    Input Parameters:
7473: +  mat - the matrix
7474: .  nblocks - the number of blocks on this process, each block can only exist on a single process
7475: -  bsizes - the block sizes

7477:    Notes:
7478:     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices

7480:     Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks.

7482:    Level: intermediate

7484: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7485:           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7486: @*/
7487: PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7488: {
7489:   PetscInt i, ncnt = 0, nlocal;

7493:   MatGetLocalSize(mat, &nlocal, NULL);
7494:   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7496:   PetscFree(mat->bsizes);
7497:   mat->nblocks = nblocks;
7498:   PetscMalloc1(nblocks, &mat->bsizes);
7499:   PetscArraycpy(mat->bsizes, bsizes, nblocks);
7500:   return 0;
7501: }

7503: /*@C
7504:    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size

7506:    Logically Collective on mat

7508:    Input Parameter:
7509: .  mat - the matrix

7511:    Output Parameters:
7512: +  nblocks - the number of blocks on this process
7513: -  bsizes - the block sizes

7515:    Fortran Note:
7516:    Currently not supported from Fortran

7518:    Level: intermediate

7520: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7521: @*/
7522: PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7523: {
7525:   *nblocks = mat->nblocks;
7526:   *bsizes  = mat->bsizes;
7527:   return 0;
7528: }

7530: /*@
7531:    MatSetBlockSizes - Sets the matrix block row and column sizes.

7533:    Logically Collective on mat

7535:    Input Parameters:
7536: +  mat - the matrix
7537: .  rbs - row block size
7538: -  cbs - column block size

7540:    Notes:
7541:     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7542:     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7543:     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.

7545:     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7546:     are compatible with the matrix local sizes.

7548:     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.

7550:    Level: intermediate

7552: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7553: @*/
7554: PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7555: {
7559:   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7560:   if (mat->rmap->refcnt) {
7561:     ISLocalToGlobalMapping l2g  = NULL;
7562:     PetscLayout            nmap = NULL;

7564:     PetscLayoutDuplicate(mat->rmap, &nmap);
7565:     if (mat->rmap->mapping) ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g);
7566:     PetscLayoutDestroy(&mat->rmap);
7567:     mat->rmap          = nmap;
7568:     mat->rmap->mapping = l2g;
7569:   }
7570:   if (mat->cmap->refcnt) {
7571:     ISLocalToGlobalMapping l2g  = NULL;
7572:     PetscLayout            nmap = NULL;

7574:     PetscLayoutDuplicate(mat->cmap, &nmap);
7575:     if (mat->cmap->mapping) ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g);
7576:     PetscLayoutDestroy(&mat->cmap);
7577:     mat->cmap          = nmap;
7578:     mat->cmap->mapping = l2g;
7579:   }
7580:   PetscLayoutSetBlockSize(mat->rmap, rbs);
7581:   PetscLayoutSetBlockSize(mat->cmap, cbs);
7582:   return 0;
7583: }

7585: /*@
7586:    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices

7588:    Logically Collective on mat

7590:    Input Parameters:
7591: +  mat - the matrix
7592: .  fromRow - matrix from which to copy row block size
7593: -  fromCol - matrix from which to copy column block size (can be same as fromRow)

7595:    Level: developer

7597: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7598: @*/
7599: PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7600: {
7604:   if (fromRow->rmap->bs > 0) PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs);
7605:   if (fromCol->cmap->bs > 0) PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs);
7606:   return 0;
7607: }

7609: /*@
7610:    MatResidual - Default routine to calculate the residual r = b - Ax

7612:    Collective on mat

7614:    Input Parameters:
7615: +  mat - the matrix
7616: .  b   - the right-hand-side
7617: -  x   - the approximate solution

7619:    Output Parameter:
7620: .  r - location to store the residual

7622:    Level: developer

7624: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7625: @*/
7626: PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7627: {
7633:   MatCheckPreallocated(mat, 1);
7634:   PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0);
7635:   if (!mat->ops->residual) {
7636:     MatMult(mat, x, r);
7637:     VecAYPX(r, -1.0, b);
7638:   } else {
7639:     PetscUseTypeMethod(mat, residual, b, x, r);
7640:   }
7641:   PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0);
7642:   return 0;
7643: }

7645: /*@C
7646:     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix

7648:    Collective on mat

7650:     Input Parameters:
7651: +   mat - the matrix
7652: .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7653: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7654: -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7655:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7656:                  always used.

7658:     Output Parameters:
7659: +   n - number of local rows in the (possibly compressed) matrix, use NULL if not needed
7660: .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix, use NULL if not needed
7661: .   ja - the column indices, use NULL if not needed
7662: -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7663:            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set

7665:     Level: developer

7667:     Notes:
7668:     You CANNOT change any of the ia[] or ja[] values.

7670:     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.

7672:     Fortran Notes:
7673:     In Fortran use
7674: $
7675: $      PetscInt ia(1), ja(1)
7676: $      PetscOffset iia, jja
7677: $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7678: $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)

7680:      or
7681: $
7682: $    PetscInt, pointer :: ia(:),ja(:)
7683: $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7684: $    ! Access the ith and jth entries via ia(i) and ja(j)

7686: .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7687: @*/
7688: PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7689: {
7696:   MatCheckPreallocated(mat, 1);
7697:   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7698:   else {
7699:     if (done) *done = PETSC_TRUE;
7700:     PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0);
7701:     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7702:     PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0);
7703:   }
7704:   return 0;
7705: }

7707: /*@C
7708:     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.

7710:     Collective on mat

7712:     Input Parameters:
7713: +   mat - the matrix
7714: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7715: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7716:                 symmetrized
7717: .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7718:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7719:                  always used.
7720: .   n - number of columns in the (possibly compressed) matrix
7721: .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7722: -   ja - the row indices

7724:     Output Parameters:
7725: .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned

7727:     Level: developer

7729: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7730: @*/
7731: PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7732: {
7739:   MatCheckPreallocated(mat, 1);
7740:   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7741:   else {
7742:     *done = PETSC_TRUE;
7743:     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7744:   }
7745:   return 0;
7746: }

7748: /*@C
7749:     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.

7751:     Collective on mat

7753:     Input Parameters:
7754: +   mat - the matrix
7755: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7756: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7757: .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7758:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7759:                  always used.
7760: .   n - size of (possibly compressed) matrix
7761: .   ia - the row pointers
7762: -   ja - the column indices

7764:     Output Parameters:
7765: .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned

7767:     Note:
7768:     This routine zeros out n, ia, and ja. This is to prevent accidental
7769:     us of the array after it has been restored. If you pass NULL, it will
7770:     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.

7772:     Level: developer

7774: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7775: @*/
7776: PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7777: {
7783:   MatCheckPreallocated(mat, 1);

7785:   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7786:   else {
7787:     if (done) *done = PETSC_TRUE;
7788:     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7789:     if (n) *n = 0;
7790:     if (ia) *ia = NULL;
7791:     if (ja) *ja = NULL;
7792:   }
7793:   return 0;
7794: }

7796: /*@C
7797:     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.

7799:     Collective on Mat

7801:     Input Parameters:
7802: +   mat - the matrix
7803: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7804: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7805: -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7806:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7807:                  always used.

7809:     Output Parameters:
7810: +   n - size of (possibly compressed) matrix
7811: .   ia - the column pointers
7812: .   ja - the row indices
7813: -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned

7815:     Level: developer

7817: .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7818: @*/
7819: PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7820: {
7826:   MatCheckPreallocated(mat, 1);

7828:   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7829:   else {
7830:     *done = PETSC_TRUE;
7831:     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7832:     if (n) *n = 0;
7833:     if (ia) *ia = NULL;
7834:     if (ja) *ja = NULL;
7835:   }
7836:   return 0;
7837: }

7839: /*@C
7840:     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.

7842:     Collective on mat

7844:     Input Parameters:
7845: +   mat - the matrix
7846: .   ncolors - max color value
7847: .   n   - number of entries in colorarray
7848: -   colorarray - array indicating color for each column

7850:     Output Parameters:
7851: .   iscoloring - coloring generated using colorarray information

7853:     Level: developer

7855: .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7856: @*/
7857: PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
7858: {
7863:   MatCheckPreallocated(mat, 1);

7865:   if (!mat->ops->coloringpatch) {
7866:     ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring);
7867:   } else {
7868:     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7869:   }
7870:   return 0;
7871: }

7873: /*@
7874:    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.

7876:    Logically Collective on mat

7878:    Input Parameter:
7879: .  mat - the factored matrix to be reset

7881:    Notes:
7882:    This routine should be used only with factored matrices formed by in-place
7883:    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
7884:    format).  This option can save memory, for example, when solving nonlinear
7885:    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7886:    ILU(0) preconditioner.

7888:    Note that one can specify in-place ILU(0) factorization by calling
7889: .vb
7890:      PCType(pc,PCILU);
7891:      PCFactorSeUseInPlace(pc);
7892: .ve
7893:    or by using the options -pc_type ilu -pc_factor_in_place

7895:    In-place factorization ILU(0) can also be used as a local
7896:    solver for the blocks within the block Jacobi or additive Schwarz
7897:    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
7898:    for details on setting local solver options.

7900:    Most users should employ the `KSP` interface for linear solvers
7901:    instead of working directly with matrix algebra routines such as this.
7902:    See, e.g., `KSPCreate()`.

7904:    Level: developer

7906: .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7907: @*/
7908: PetscErrorCode MatSetUnfactored(Mat mat)
7909: {
7912:   MatCheckPreallocated(mat, 1);
7913:   mat->factortype = MAT_FACTOR_NONE;
7914:   if (!mat->ops->setunfactored) return 0;
7915:   PetscUseTypeMethod(mat, setunfactored);
7916:   return 0;
7917: }

7919: /*MC
7920:     MatDenseGetArrayF90 - Accesses a matrix array from Fortran

7922:     Synopsis:
7923:     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)

7925:     Not collective

7927:     Input Parameter:
7928: .   x - matrix

7930:     Output Parameters:
7931: +   xx_v - the Fortran pointer to the array
7932: -   ierr - error code

7934:     Example of Usage:
7935: .vb
7936:       PetscScalar, pointer xx_v(:,:)
7937:       ....
7938:       call MatDenseGetArrayF90(x,xx_v,ierr)
7939:       a = xx_v(3)
7940:       call MatDenseRestoreArrayF90(x,xx_v,ierr)
7941: .ve

7943:     Level: advanced

7945: .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`

7947: M*/

7949: /*MC
7950:     MatDenseRestoreArrayF90 - Restores a matrix array that has been
7951:     accessed with `MatDenseGetArrayF90()`.

7953:     Synopsis:
7954:     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)

7956:     Not collective

7958:     Input Parameters:
7959: +   x - matrix
7960: -   xx_v - the Fortran90 pointer to the array

7962:     Output Parameter:
7963: .   ierr - error code

7965:     Example of Usage:
7966: .vb
7967:        PetscScalar, pointer xx_v(:,:)
7968:        ....
7969:        call MatDenseGetArrayF90(x,xx_v,ierr)
7970:        a = xx_v(3)
7971:        call MatDenseRestoreArrayF90(x,xx_v,ierr)
7972: .ve

7974:     Level: advanced

7976: .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`

7978: M*/

7980: /*MC
7981:     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.

7983:     Synopsis:
7984:     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)

7986:     Not collective

7988:     Input Parameter:
7989: .   x - matrix

7991:     Output Parameters:
7992: +   xx_v - the Fortran pointer to the array
7993: -   ierr - error code

7995:     Example of Usage:
7996: .vb
7997:       PetscScalar, pointer xx_v(:)
7998:       ....
7999:       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8000:       a = xx_v(3)
8001:       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8002: .ve

8004:     Level: advanced

8006: .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`

8008: M*/

8010: /*MC
8011:     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8012:     accessed with `MatSeqAIJGetArrayF90()`.

8014:     Synopsis:
8015:     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)

8017:     Not collective

8019:     Input Parameters:
8020: +   x - matrix
8021: -   xx_v - the Fortran90 pointer to the array

8023:     Output Parameter:
8024: .   ierr - error code

8026:     Example of Usage:
8027: .vb
8028:        PetscScalar, pointer xx_v(:)
8029:        ....
8030:        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8031:        a = xx_v(3)
8032:        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8033: .ve

8035:     Level: advanced

8037: .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`

8039: M*/

8041: /*@
8042:     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8043:                       as the original matrix.

8045:     Collective on mat

8047:     Input Parameters:
8048: +   mat - the original matrix
8049: .   isrow - parallel IS containing the rows this processor should obtain
8050: .   iscol - parallel IS containing all columns you wish to keep. Each process should list the columns that will be in IT's "diagonal part" in the new matrix.
8051: -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

8053:     Output Parameter:
8054: .   newmat - the new submatrix, of the same type as the old

8056:     Level: advanced

8058:     Notes:
8059:     The submatrix will be able to be multiplied with vectors using the same layout as iscol.

8061:     Some matrix types place restrictions on the row and column indices, such
8062:     as that they be sorted or that they be equal to each other.

8064:     The index sets may not have duplicate entries.

8066:       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8067:    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8068:    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8069:    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8070:    you are finished using it.

8072:     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8073:     the input matrix.

8075:     If iscol is NULL then all columns are obtained (not supported in Fortran).

8077:    Example usage:
8078:    Consider the following 8x8 matrix with 34 non-zero values, that is
8079:    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8080:    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8081:    as follows:

8083: .vb
8084:             1  2  0  |  0  3  0  |  0  4
8085:     Proc0   0  5  6  |  7  0  0  |  8  0
8086:             9  0 10  | 11  0  0  | 12  0
8087:     -------------------------------------
8088:            13  0 14  | 15 16 17  |  0  0
8089:     Proc1   0 18  0  | 19 20 21  |  0  0
8090:             0  0  0  | 22 23  0  | 24  0
8091:     -------------------------------------
8092:     Proc2  25 26 27  |  0  0 28  | 29  0
8093:            30  0  0  | 31 32 33  |  0 34
8094: .ve

8096:     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is

8098: .vb
8099:             2  0  |  0  3  0  |  0
8100:     Proc0   5  6  |  7  0  0  |  8
8101:     -------------------------------
8102:     Proc1  18  0  | 19 20 21  |  0
8103:     -------------------------------
8104:     Proc2  26 27  |  0  0 28  | 29
8105:             0  0  | 31 32 33  |  0
8106: .ve

8108: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8109: @*/
8110: PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8111: {
8112:   PetscMPIInt size;
8113:   Mat        *local;
8114:   IS          iscoltmp;
8115:   PetscBool   flg;


8126:   MatCheckPreallocated(mat, 1);
8127:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);

8129:   if (!iscol || isrow == iscol) {
8130:     PetscBool   stride;
8131:     PetscMPIInt grabentirematrix = 0, grab;
8132:     PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride);
8133:     if (stride) {
8134:       PetscInt first, step, n, rstart, rend;
8135:       ISStrideGetInfo(isrow, &first, &step);
8136:       if (step == 1) {
8137:         MatGetOwnershipRange(mat, &rstart, &rend);
8138:         if (rstart == first) {
8139:           ISGetLocalSize(isrow, &n);
8140:           if (n == rend - rstart) grabentirematrix = 1;
8141:         }
8142:       }
8143:     }
8144:     MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat));
8145:     if (grab) {
8146:       PetscInfo(mat, "Getting entire matrix as submatrix\n");
8147:       if (cll == MAT_INITIAL_MATRIX) {
8148:         *newmat = mat;
8149:         PetscObjectReference((PetscObject)mat);
8150:       }
8151:       return 0;
8152:     }
8153:   }

8155:   if (!iscol) {
8156:     ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp);
8157:   } else {
8158:     iscoltmp = iscol;
8159:   }

8161:   /* if original matrix is on just one processor then use submatrix generated */
8162:   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8163:     MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat);
8164:     goto setproperties;
8165:   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8166:     MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local);
8167:     *newmat = *local;
8168:     PetscFree(local);
8169:     goto setproperties;
8170:   } else if (!mat->ops->createsubmatrix) {
8171:     /* Create a new matrix type that implements the operation using the full matrix */
8172:     PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8173:     switch (cll) {
8174:     case MAT_INITIAL_MATRIX:
8175:       MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat);
8176:       break;
8177:     case MAT_REUSE_MATRIX:
8178:       MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp);
8179:       break;
8180:     default:
8181:       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8182:     }
8183:     PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8184:     goto setproperties;
8185:   }

8187:   PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8188:   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8189:   PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);

8191: setproperties:
8192:   ISEqualUnsorted(isrow, iscoltmp, &flg);
8193:   if (flg) MatPropagateSymmetryOptions(mat, *newmat);
8194:   if (!iscol) ISDestroy(&iscoltmp);
8195:   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscObjectStateIncrease((PetscObject)*newmat);
8196:   return 0;
8197: }

8199: /*@
8200:    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix

8202:    Not Collective

8204:    Input Parameters:
8205: +  A - the matrix we wish to propagate options from
8206: -  B - the matrix we wish to propagate options to

8208:    Level: beginner

8210:    Note:
8211:    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`

8213: .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8214: @*/
8215: PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8216: {
8219:   B->symmetry_eternal            = A->symmetry_eternal;
8220:   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8221:   B->symmetric                   = A->symmetric;
8222:   B->structurally_symmetric      = A->structurally_symmetric;
8223:   B->spd                         = A->spd;
8224:   B->hermitian                   = A->hermitian;
8225:   return 0;
8226: }

8228: /*@
8229:    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8230:    used during the assembly process to store values that belong to
8231:    other processors.

8233:    Not Collective

8235:    Input Parameters:
8236: +  mat   - the matrix
8237: .  size  - the initial size of the stash.
8238: -  bsize - the initial size of the block-stash(if used).

8240:    Options Database Keys:
8241: +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8242: -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>

8244:    Level: intermediate

8246:    Notes:
8247:      The block-stash is used for values set with `MatSetValuesBlocked()` while
8248:      the stash is used for values set with `MatSetValues()`

8250:      Run with the option -info and look for output of the form
8251:      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8252:      to determine the appropriate value, MM, to use for size and
8253:      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8254:      to determine the value, BMM to use for bsize

8256: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8257: @*/
8258: PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8259: {
8262:   MatStashSetInitialSize_Private(&mat->stash, size);
8263:   MatStashSetInitialSize_Private(&mat->bstash, bsize);
8264:   return 0;
8265: }

8267: /*@
8268:    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8269:      the matrix

8271:    Neighbor-wise Collective on mat

8273:    Input Parameters:
8274: +  mat   - the matrix
8275: .  x,y - the vectors
8276: -  w - where the result is stored

8278:    Level: intermediate

8280:    Notes:
8281:     w may be the same vector as y.

8283:     This allows one to use either the restriction or interpolation (its transpose)
8284:     matrix to do the interpolation

8286: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8287: @*/
8288: PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8289: {
8290:   PetscInt M, N, Ny;

8296:   MatGetSize(A, &M, &N);
8297:   VecGetSize(y, &Ny);
8298:   if (M == Ny) {
8299:     MatMultAdd(A, x, y, w);
8300:   } else {
8301:     MatMultTransposeAdd(A, x, y, w);
8302:   }
8303:   return 0;
8304: }

8306: /*@
8307:    MatInterpolate - y = A*x or A'*x depending on the shape of
8308:      the matrix

8310:    Neighbor-wise Collective on mat

8312:    Input Parameters:
8313: +  mat   - the matrix
8314: -  x,y - the vectors

8316:    Level: intermediate

8318:    Note:
8319:     This allows one to use either the restriction or interpolation (its transpose)
8320:     matrix to do the interpolation

8322: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8323: @*/
8324: PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8325: {
8326:   PetscInt M, N, Ny;

8331:   MatGetSize(A, &M, &N);
8332:   VecGetSize(y, &Ny);
8333:   if (M == Ny) {
8334:     MatMult(A, x, y);
8335:   } else {
8336:     MatMultTranspose(A, x, y);
8337:   }
8338:   return 0;
8339: }

8341: /*@
8342:    MatRestrict - y = A*x or A'*x

8344:    Neighbor-wise Collective on Mat

8346:    Input Parameters:
8347: +  mat   - the matrix
8348: -  x,y - the vectors

8350:    Level: intermediate

8352:    Note:
8353:     This allows one to use either the restriction or interpolation (its transpose)
8354:     matrix to do the restriction

8356: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8357: @*/
8358: PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8359: {
8360:   PetscInt M, N, Ny;

8365:   MatGetSize(A, &M, &N);
8366:   VecGetSize(y, &Ny);
8367:   if (M == Ny) {
8368:     MatMult(A, x, y);
8369:   } else {
8370:     MatMultTranspose(A, x, y);
8371:   }
8372:   return 0;
8373: }

8375: /*@
8376:    MatMatInterpolateAdd - Y = W + A*X or W + A'*X

8378:    Neighbor-wise Collective on Mat

8380:    Input Parameters:
8381: +  mat   - the matrix
8382: -  w, x - the input dense matrices

8384:    Output Parameters:
8385: .  y - the output dense matrix

8387:    Level: intermediate

8389:    Note:
8390:     This allows one to use either the restriction or interpolation (its transpose)
8391:     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8392:     otherwise it will be recreated. y must be initialized to NULL if not supplied.

8394: .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8395: @*/
8396: PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8397: {
8398:   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8399:   PetscBool trans = PETSC_TRUE;
8400:   MatReuse  reuse = MAT_INITIAL_MATRIX;

8407:   MatGetSize(A, &M, &N);
8408:   MatGetSize(x, &Mx, &Nx);
8409:   if (N == Mx) trans = PETSC_FALSE;
8411:   Mo = trans ? N : M;
8412:   if (*y) {
8413:     MatGetSize(*y, &My, &Ny);
8414:     if (Mo == My && Nx == Ny) {
8415:       reuse = MAT_REUSE_MATRIX;
8416:     } else {
8418:       MatDestroy(y);
8419:     }
8420:   }

8422:   if (w && *y == w) { /* this is to minimize changes in PCMG */
8423:     PetscBool flg;

8425:     PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w);
8426:     if (w) {
8427:       PetscInt My, Ny, Mw, Nw;

8429:       PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg);
8430:       MatGetSize(*y, &My, &Ny);
8431:       MatGetSize(w, &Mw, &Nw);
8432:       if (!flg || My != Mw || Ny != Nw) w = NULL;
8433:     }
8434:     if (!w) {
8435:       MatDuplicate(*y, MAT_COPY_VALUES, &w);
8436:       PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w);
8437:       PetscObjectDereference((PetscObject)w);
8438:     } else {
8439:       MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN);
8440:     }
8441:   }
8442:   if (!trans) {
8443:     MatMatMult(A, x, reuse, PETSC_DEFAULT, y);
8444:   } else {
8445:     MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y);
8446:   }
8447:   if (w) MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN);
8448:   return 0;
8449: }

8451: /*@
8452:    MatMatInterpolate - Y = A*X or A'*X

8454:    Neighbor-wise Collective on Mat

8456:    Input Parameters:
8457: +  mat   - the matrix
8458: -  x - the input dense matrix

8460:    Output Parameters:
8461: .  y - the output dense matrix

8463:    Level: intermediate

8465:    Note:
8466:     This allows one to use either the restriction or interpolation (its transpose)
8467:     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8468:     otherwise it will be recreated. y must be initialized to NULL if not supplied.

8470: .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8471: @*/
8472: PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8473: {
8474:   MatMatInterpolateAdd(A, x, NULL, y);
8475:   return 0;
8476: }

8478: /*@
8479:    MatMatRestrict - Y = A*X or A'*X

8481:    Neighbor-wise Collective on Mat

8483:    Input Parameters:
8484: +  mat   - the matrix
8485: -  x - the input dense matrix

8487:    Output Parameters:
8488: .  y - the output dense matrix

8490:    Level: intermediate

8492:    Note:
8493:     This allows one to use either the restriction or interpolation (its transpose)
8494:     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8495:     otherwise it will be recreated. y must be initialized to NULL if not supplied.

8497: .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8498: @*/
8499: PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8500: {
8501:   MatMatInterpolateAdd(A, x, NULL, y);
8502:   return 0;
8503: }

8505: /*@
8506:    MatGetNullSpace - retrieves the null space of a matrix.

8508:    Logically Collective on mat

8510:    Input Parameters:
8511: +  mat - the matrix
8512: -  nullsp - the null space object

8514:    Level: developer

8516: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8517: @*/
8518: PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8519: {
8522:   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8523:   return 0;
8524: }

8526: /*@
8527:    MatSetNullSpace - attaches a null space to a matrix.

8529:    Logically Collective on mat

8531:    Input Parameters:
8532: +  mat - the matrix
8533: -  nullsp - the null space object

8535:    Level: advanced

8537:    Notes:
8538:       This null space is used by the `KSP` linear solvers to solve singular systems.

8540:       Overwrites any previous null space that may have been attached. You can remove the null space from the matrix object by calling this routine with an nullsp of NULL

8542:       For inconsistent singular systems (linear systems where the right hand side is not in the range of the operator) the `KSP` residuals will not converge to
8543:       to zero but the linear system will still be solved in a least squares sense.

8545:       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8546:    the domain of a matrix A (from R^n to R^m (m rows, n columns) R^n = the direct sum of the null space of A, n(A), + the range of A^T, R(A^T).
8547:    Similarly R^m = direct sum n(A^T) + R(A).  Hence the linear system A x = b has a solution only if b in R(A) (or correspondingly b is orthogonal to
8548:    n(A^T)) and if x is a solution then x + alpha n(A) is a solution for any alpha. The minimum norm solution is orthogonal to n(A). For problems without a solution
8549:    the solution that minimizes the norm of the residual (the least squares solution) can be obtained by solving A x = \hat{b} where \hat{b} is b orthogonalized to the n(A^T).
8550:    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.

8552:     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8553:     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8554:     routine also automatically calls `MatSetTransposeNullSpace()`.

8556:     The user should call `MatNullSpaceDestroy()`.

8558: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8559:           `KSPSetPCSide()`
8560: @*/
8561: PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8562: {
8565:   if (nullsp) PetscObjectReference((PetscObject)nullsp);
8566:   MatNullSpaceDestroy(&mat->nullsp);
8567:   mat->nullsp = nullsp;
8568:   if (mat->symmetric == PETSC_BOOL3_TRUE) MatSetTransposeNullSpace(mat, nullsp);
8569:   return 0;
8570: }

8572: /*@
8573:    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.

8575:    Logically Collective on mat

8577:    Input Parameters:
8578: +  mat - the matrix
8579: -  nullsp - the null space object

8581:    Level: developer

8583: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8584: @*/
8585: PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8586: {
8590:   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8591:   return 0;
8592: }

8594: /*@
8595:    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix

8597:    Logically Collective on mat

8599:    Input Parameters:
8600: +  mat - the matrix
8601: -  nullsp - the null space object

8603:    Level: advanced

8605:    Notes:
8606:    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.

8608:    See `MatSetNullSpace()`

8610: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8611: @*/
8612: PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8613: {
8616:   if (nullsp) PetscObjectReference((PetscObject)nullsp);
8617:   MatNullSpaceDestroy(&mat->transnullsp);
8618:   mat->transnullsp = nullsp;
8619:   return 0;
8620: }

8622: /*@
8623:    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8624:         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.

8626:    Logically Collective on mat

8628:    Input Parameters:
8629: +  mat - the matrix
8630: -  nullsp - the null space object

8632:    Level: advanced

8634:    Notes:
8635:    Overwrites any previous near null space that may have been attached

8637:    You can remove the null space by calling this routine with an nullsp of NULL

8639: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8640: @*/
8641: PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8642: {
8646:   MatCheckPreallocated(mat, 1);
8647:   if (nullsp) PetscObjectReference((PetscObject)nullsp);
8648:   MatNullSpaceDestroy(&mat->nearnullsp);
8649:   mat->nearnullsp = nullsp;
8650:   return 0;
8651: }

8653: /*@
8654:    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`

8656:    Not Collective

8658:    Input Parameter:
8659: .  mat - the matrix

8661:    Output Parameter:
8662: .  nullsp - the null space object, NULL if not set

8664:    Level: advanced

8666: .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8667: @*/
8668: PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8669: {
8673:   MatCheckPreallocated(mat, 1);
8674:   *nullsp = mat->nearnullsp;
8675:   return 0;
8676: }

8678: /*@C
8679:    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.

8681:    Collective on mat

8683:    Input Parameters:
8684: +  mat - the matrix
8685: .  row - row/column permutation
8686: .  fill - expected fill factor >= 1.0
8687: -  level - level of fill, for ICC(k)

8689:    Notes:
8690:    Probably really in-place only when level of fill is zero, otherwise allocates
8691:    new space to store factored matrix and deletes previous memory.

8693:    Most users should employ the `KSP` interface for linear solvers
8694:    instead of working directly with matrix algebra routines such as this.
8695:    See, e.g., `KSPCreate()`.

8697:    Level: developer

8699:    Developer Note:
8700:    The Fortran interface is not autogenerated as the f90
8701:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

8703: .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8704: @*/
8705: PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8706: {
8714:   MatCheckPreallocated(mat, 1);
8715:   PetscUseTypeMethod(mat, iccfactor, row, info);
8716:   PetscObjectStateIncrease((PetscObject)mat);
8717:   return 0;
8718: }

8720: /*@
8721:    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8722:          ghosted ones.

8724:    Not Collective

8726:    Input Parameters:
8727: +  mat - the matrix
8728: -  diag - the diagonal values, including ghost ones

8730:    Level: developer

8732:    Notes:
8733:     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices

8735:     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`

8737: .seealso: `MatDiagonalScale()`
8738: @*/
8739: PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8740: {
8741:   PetscMPIInt size;


8748:   PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
8749:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8750:   if (size == 1) {
8751:     PetscInt n, m;
8752:     VecGetSize(diag, &n);
8753:     MatGetSize(mat, NULL, &m);
8754:     if (m == n) {
8755:       MatDiagonalScale(mat, NULL, diag);
8756:     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8757:   } else {
8758:     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8759:   }
8760:   PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
8761:   PetscObjectStateIncrease((PetscObject)mat);
8762:   return 0;
8763: }

8765: /*@
8766:    MatGetInertia - Gets the inertia from a factored matrix

8768:    Collective on mat

8770:    Input Parameter:
8771: .  mat - the matrix

8773:    Output Parameters:
8774: +   nneg - number of negative eigenvalues
8775: .   nzero - number of zero eigenvalues
8776: -   npos - number of positive eigenvalues

8778:    Level: advanced

8780:    Note:
8781:     Matrix must have been factored by `MatCholeskyFactor()`

8783: .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8784: @*/
8785: PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8786: {
8791:   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8792:   return 0;
8793: }

8795: /* ----------------------------------------------------------------*/
8796: /*@C
8797:    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors

8799:    Neighbor-wise Collective on mat

8801:    Input Parameters:
8802: +  mat - the factored matrix obtained with `MatGetFactor()`
8803: -  b - the right-hand-side vectors

8805:    Output Parameter:
8806: .  x - the result vectors

8808:    Note:
8809:    The vectors b and x cannot be the same.  I.e., one cannot
8810:    call `MatSolves`(A,x,x).

8812:    Level: developer

8814: .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8815: @*/
8816: PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
8817: {
8822:   if (!mat->rmap->N && !mat->cmap->N) return 0;

8824:   MatCheckPreallocated(mat, 1);
8825:   PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0);
8826:   PetscUseTypeMethod(mat, solves, b, x);
8827:   PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0);
8828:   return 0;
8829: }

8831: /*@
8832:    MatIsSymmetric - Test whether a matrix is symmetric

8834:    Collective on mat

8836:    Input Parameters:
8837: +  A - the matrix to test
8838: -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)

8840:    Output Parameters:
8841: .  flg - the result

8843:    Notes:
8844:     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results

8846:     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`

8848:     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8849:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

8851:    Level: intermediate

8853: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
8854:           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8855: @*/
8856: PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
8857: {

8861:   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8862:   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8863:   else {
8864:     if (!A->ops->issymmetric) {
8865:       MatType mattype;
8866:       MatGetType(A, &mattype);
8867:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8868:     }
8869:     PetscUseTypeMethod(A, issymmetric, tol, flg);
8870:     if (!tol) MatSetOption(A, MAT_SYMMETRIC, *flg);
8871:   }
8872:   return 0;
8873: }

8875: /*@
8876:    MatIsHermitian - Test whether a matrix is Hermitian

8878:    Collective on Mat

8880:    Input Parameters:
8881: +  A - the matrix to test
8882: -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)

8884:    Output Parameters:
8885: .  flg - the result

8887:    Level: intermediate

8889:    Notes:
8890:     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results

8892:     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`

8894:     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8895:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)

8897: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8898:           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8899: @*/
8900: PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
8901: {

8905:   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8906:   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8907:   else {
8908:     if (!A->ops->ishermitian) {
8909:       MatType mattype;
8910:       MatGetType(A, &mattype);
8911:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8912:     }
8913:     PetscUseTypeMethod(A, ishermitian, tol, flg);
8914:     if (!tol) MatSetOption(A, MAT_HERMITIAN, *flg);
8915:   }
8916:   return 0;
8917: }

8919: /*@
8920:    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state

8922:    Not Collective

8924:    Input Parameter:
8925: .  A - the matrix to check

8927:    Output Parameters:
8928: +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
8929: -  flg - the result (only valid if set is `PETSC_TRUE`)

8931:    Level: advanced

8933:    Notes:
8934:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
8935:    if you want it explicitly checked

8937:     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8938:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

8940: .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8941: @*/
8942: PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
8943: {
8947:   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8948:     *set = PETSC_TRUE;
8949:     *flg = PetscBool3ToBool(A->symmetric);
8950:   } else {
8951:     *set = PETSC_FALSE;
8952:   }
8953:   return 0;
8954: }

8956: /*@
8957:    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state

8959:    Not Collective

8961:    Input Parameter:
8962: .  A - the matrix to check

8964:    Output Parameters:
8965: +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
8966: -  flg - the result (only valid if set is `PETSC_TRUE`)

8968:    Level: advanced

8970:    Notes:
8971:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).

8973:    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
8974:    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)

8976: .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8977: @*/
8978: PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
8979: {
8983:   if (A->spd != PETSC_BOOL3_UNKNOWN) {
8984:     *set = PETSC_TRUE;
8985:     *flg = PetscBool3ToBool(A->spd);
8986:   } else {
8987:     *set = PETSC_FALSE;
8988:   }
8989:   return 0;
8990: }

8992: /*@
8993:    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state

8995:    Not Collective

8997:    Input Parameter:
8998: .  A - the matrix to check

9000:    Output Parameters:
9001: +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9002: -  flg - the result (only valid if set is `PETSC_TRUE`)

9004:    Level: advanced

9006:    Notes:
9007:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9008:    if you want it explicitly checked

9010:    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9011:    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9013: .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9014: @*/
9015: PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9016: {
9020:   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9021:     *set = PETSC_TRUE;
9022:     *flg = PetscBool3ToBool(A->hermitian);
9023:   } else {
9024:     *set = PETSC_FALSE;
9025:   }
9026:   return 0;
9027: }

9029: /*@
9030:    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric

9032:    Collective on Mat

9034:    Input Parameter:
9035: .  A - the matrix to test

9037:    Output Parameters:
9038: .  flg - the result

9040:    Notes:
9041:    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`

9043:    One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9044:    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9046:    Level: intermediate

9048: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9049: @*/
9050: PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9051: {
9054:   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9055:     *flg = PetscBool3ToBool(A->structurally_symmetric);
9056:   } else {
9057:     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9058:     MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg);
9059:   }
9060:   return 0;
9061: }

9063: /*@
9064:    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state

9066:    Not Collective

9068:    Input Parameter:
9069: .  A - the matrix to check

9071:    Output Parameters:
9072: +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9073: -  flg - the result (only valid if set is PETSC_TRUE)

9075:    Level: advanced

9077:    Notes:
9078:    One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9079:    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9081:    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)

9083: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9084: @*/
9085: PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9086: {
9090:   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9091:     *set = PETSC_TRUE;
9092:     *flg = PetscBool3ToBool(A->structurally_symmetric);
9093:   } else {
9094:     *set = PETSC_FALSE;
9095:   }
9096:   return 0;
9097: }

9099: /*@
9100:    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9101:        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process

9103:     Not collective

9105:    Input Parameter:
9106: .   mat - the matrix

9108:    Output Parameters:
9109: +   nstash   - the size of the stash
9110: .   reallocs - the number of additional mallocs incurred.
9111: .   bnstash   - the size of the block stash
9112: -   breallocs - the number of additional mallocs incurred.in the block stash

9114:    Level: advanced

9116: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9117: @*/
9118: PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9119: {
9120:   MatStashGetInfo_Private(&mat->stash, nstash, reallocs);
9121:   MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs);
9122:   return 0;
9123: }

9125: /*@C
9126:    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9127:    parallel layout, `PetscLayout` for rows and columns

9129:    Collective on mat

9131:    Input Parameter:
9132: .  mat - the matrix

9134:    Output Parameters:
9135: +   right - (optional) vector that the matrix can be multiplied against
9136: -   left - (optional) vector that the matrix vector product can be stored in

9138:    Notes:
9139:     The blocksize of the returned vectors is determined by the row and column block sizes set with `MatSetBlockSizes()` or the single blocksize (same for both) set by `MatSetBlockSize()`.

9141:     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed

9143:   Level: advanced

9145: .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9146: @*/
9147: PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9148: {
9151:   if (mat->ops->getvecs) {
9152:     PetscUseTypeMethod(mat, getvecs, right, left);
9153:   } else {
9154:     PetscInt rbs, cbs;
9155:     MatGetBlockSizes(mat, &rbs, &cbs);
9156:     if (right) {
9158:       VecCreate(PetscObjectComm((PetscObject)mat), right);
9159:       VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE);
9160:       VecSetBlockSize(*right, cbs);
9161:       VecSetType(*right, mat->defaultvectype);
9162: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9163:       if (mat->boundtocpu && mat->bindingpropagates) {
9164:         VecSetBindingPropagates(*right, PETSC_TRUE);
9165:         VecBindToCPU(*right, PETSC_TRUE);
9166:       }
9167: #endif
9168:       PetscLayoutReference(mat->cmap, &(*right)->map);
9169:     }
9170:     if (left) {
9172:       VecCreate(PetscObjectComm((PetscObject)mat), left);
9173:       VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE);
9174:       VecSetBlockSize(*left, rbs);
9175:       VecSetType(*left, mat->defaultvectype);
9176: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9177:       if (mat->boundtocpu && mat->bindingpropagates) {
9178:         VecSetBindingPropagates(*left, PETSC_TRUE);
9179:         VecBindToCPU(*left, PETSC_TRUE);
9180:       }
9181: #endif
9182:       PetscLayoutReference(mat->rmap, &(*left)->map);
9183:     }
9184:   }
9185:   return 0;
9186: }

9188: /*@C
9189:    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9190:      with default values.

9192:    Not Collective

9194:    Input Parameters:
9195: .    info - the `MatFactorInfo` data structure

9197:    Notes:
9198:     The solvers are generally used through the `KSP` and `PC` objects, for example
9199:           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`

9201:     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed

9203:    Level: developer

9205:    Developer Note:
9206:    The Fortran interface is not autogenerated as the f90
9207:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

9209: .seealso: `MatGetFactor()`, `MatFactorInfo`
9210: @*/
9211: PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9212: {
9213:   PetscMemzero(info, sizeof(MatFactorInfo));
9214:   return 0;
9215: }

9217: /*@
9218:    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed

9220:    Collective on mat

9222:    Input Parameters:
9223: +  mat - the factored matrix
9224: -  is - the index set defining the Schur indices (0-based)

9226:    Notes:
9227:     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.

9229:    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.

9231:    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`

9233:    Level: advanced

9235: .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9236:           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`

9238: @*/
9239: PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9240: {
9241:   PetscErrorCode (*f)(Mat, IS);

9249:   PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f);
9251:   MatDestroy(&mat->schur);
9252:   (*f)(mat, is);
9254:   return 0;
9255: }

9257: /*@
9258:   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step

9260:    Logically Collective on mat

9262:    Input Parameters:
9263: +  F - the factored matrix obtained by calling `MatGetFactor()`
9264: .  S - location where to return the Schur complement, can be NULL
9265: -  status - the status of the Schur complement matrix, can be NULL

9267:    Notes:
9268:    You must call `MatFactorSetSchurIS()` before calling this routine.

9270:    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`

9272:    The routine provides a copy of the Schur matrix stored within the solver data structures.
9273:    The caller must destroy the object when it is no longer needed.
9274:    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.

9276:    Use `MatFactorGetSchurComplement()` to get access to the Schur complement matrix inside the factored matrix instead of making a copy of it (which this function does)

9278:    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.

9280:    Developer Note:
9281:     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9282:    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.

9284:    Level: advanced

9286: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9287: @*/
9288: PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9289: {
9293:   if (S) {
9294:     PetscErrorCode (*f)(Mat, Mat *);

9296:     PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f);
9297:     if (f) {
9298:       (*f)(F, S);
9299:     } else {
9300:       MatDuplicate(F->schur, MAT_COPY_VALUES, S);
9301:     }
9302:   }
9303:   if (status) *status = F->schur_status;
9304:   return 0;
9305: }

9307: /*@
9308:   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix

9310:    Logically Collective on mat

9312:    Input Parameters:
9313: +  F - the factored matrix obtained by calling `MatGetFactor()`
9314: .  *S - location where to return the Schur complement, can be NULL
9315: -  status - the status of the Schur complement matrix, can be NULL

9317:    Notes:
9318:    You must call `MatFactorSetSchurIS()` before calling this routine.

9320:    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`

9322:    The routine returns a the Schur Complement stored within the data strutures of the solver.

9324:    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.

9326:    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.

9328:    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix

9330:    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.

9332:    Level: advanced

9334: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9335: @*/
9336: PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9337: {
9341:   if (S) *S = F->schur;
9342:   if (status) *status = F->schur_status;
9343:   return 0;
9344: }

9346: /*@
9347:   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`

9349:    Logically Collective on mat

9351:    Input Parameters:
9352: +  F - the factored matrix obtained by calling `MatGetFactor()`
9353: .  *S - location where the Schur complement is stored
9354: -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)

9356:    Level: advanced

9358: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9359: @*/
9360: PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9361: {
9363:   if (S) {
9365:     *S = NULL;
9366:   }
9367:   F->schur_status = status;
9368:   MatFactorUpdateSchurStatus_Private(F);
9369:   return 0;
9370: }

9372: /*@
9373:   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step

9375:    Logically Collective on mat

9377:    Input Parameters:
9378: +  F - the factored matrix obtained by calling `MatGetFactor()`
9379: .  rhs - location where the right hand side of the Schur complement system is stored
9380: -  sol - location where the solution of the Schur complement system has to be returned

9382:    Notes:
9383:    The sizes of the vectors should match the size of the Schur complement

9385:    Must be called after `MatFactorSetSchurIS()`

9387:    Level: advanced

9389: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9390: @*/
9391: PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9392: {
9401:   MatFactorFactorizeSchurComplement(F);
9402:   switch (F->schur_status) {
9403:   case MAT_FACTOR_SCHUR_FACTORED:
9404:     MatSolveTranspose(F->schur, rhs, sol);
9405:     break;
9406:   case MAT_FACTOR_SCHUR_INVERTED:
9407:     MatMultTranspose(F->schur, rhs, sol);
9408:     break;
9409:   default:
9410:     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9411:   }
9412:   return 0;
9413: }

9415: /*@
9416:   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step

9418:    Logically Collective on mat

9420:    Input Parameters:
9421: +  F - the factored matrix obtained by calling `MatGetFactor()`
9422: .  rhs - location where the right hand side of the Schur complement system is stored
9423: -  sol - location where the solution of the Schur complement system has to be returned

9425:    Notes:
9426:    The sizes of the vectors should match the size of the Schur complement

9428:    Must be called after `MatFactorSetSchurIS()`

9430:    Level: advanced

9432: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9433: @*/
9434: PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9435: {
9444:   MatFactorFactorizeSchurComplement(F);
9445:   switch (F->schur_status) {
9446:   case MAT_FACTOR_SCHUR_FACTORED:
9447:     MatSolve(F->schur, rhs, sol);
9448:     break;
9449:   case MAT_FACTOR_SCHUR_INVERTED:
9450:     MatMult(F->schur, rhs, sol);
9451:     break;
9452:   default:
9453:     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9454:   }
9455:   return 0;
9456: }

9458: /*@
9459:   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step

9461:    Logically Collective on F

9463:    Input Parameters:
9464: .  F - the factored matrix obtained by calling `MatGetFactor()`

9466:    Notes:
9467:     Must be called after `MatFactorSetSchurIS()`.

9469:    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.

9471:    Level: advanced

9473: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9474: @*/
9475: PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9476: {
9479:   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) return 0;
9480:   MatFactorFactorizeSchurComplement(F);
9481:   MatFactorInvertSchurComplement_Private(F);
9482:   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9483:   return 0;
9484: }

9486: /*@
9487:   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step

9489:    Logically Collective on mat

9491:    Input Parameters:
9492: .  F - the factored matrix obtained by calling `MatGetFactor()`

9494:    Note:
9495:     Must be called after `MatFactorSetSchurIS()`

9497:    Level: advanced

9499: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9500: @*/
9501: PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9502: {
9505:   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) return 0;
9506:   MatFactorFactorizeSchurComplement_Private(F);
9507:   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9508:   return 0;
9509: }

9511: /*@
9512:    MatPtAP - Creates the matrix product C = P^T * A * P

9514:    Neighbor-wise Collective on A

9516:    Input Parameters:
9517: +  A - the matrix
9518: .  P - the projection matrix
9519: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9520: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9521:           if the result is a dense matrix this is irrelevant

9523:    Output Parameters:
9524: .  C - the product matrix

9526:    Notes:
9527:    C will be created and must be destroyed by the user with `MatDestroy()`.

9529:    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done

9531:    Developer Note:
9532:    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.

9534:    Level: intermediate

9536: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9537: @*/
9538: PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9539: {
9540:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);

9543:   if (scall == MAT_INITIAL_MATRIX) {
9544:     MatProductCreate(A, P, NULL, C);
9545:     MatProductSetType(*C, MATPRODUCT_PtAP);
9546:     MatProductSetAlgorithm(*C, "default");
9547:     MatProductSetFill(*C, fill);

9549:     (*C)->product->api_user = PETSC_TRUE;
9550:     MatProductSetFromOptions(*C);
9552:     MatProductSymbolic(*C);
9553:   } else { /* scall == MAT_REUSE_MATRIX */
9554:     MatProductReplaceMats(A, P, NULL, *C);
9555:   }

9557:   MatProductNumeric(*C);
9558:   (*C)->symmetric = A->symmetric;
9559:   (*C)->spd       = A->spd;
9560:   return 0;
9561: }

9563: /*@
9564:    MatRARt - Creates the matrix product C = R * A * R^T

9566:    Neighbor-wise Collective on A

9568:    Input Parameters:
9569: +  A - the matrix
9570: .  R - the projection matrix
9571: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9572: -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9573:           if the result is a dense matrix this is irrelevant

9575:    Output Parameters:
9576: .  C - the product matrix

9578:    Notes:
9579:    C will be created and must be destroyed by the user with `MatDestroy()`.

9581:    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done

9583:    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9584:    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9585:    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9586:    We recommend using MatPtAP().

9588:    Level: intermediate

9590: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9591: @*/
9592: PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9593: {
9594:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);

9597:   if (scall == MAT_INITIAL_MATRIX) {
9598:     MatProductCreate(A, R, NULL, C);
9599:     MatProductSetType(*C, MATPRODUCT_RARt);
9600:     MatProductSetAlgorithm(*C, "default");
9601:     MatProductSetFill(*C, fill);

9603:     (*C)->product->api_user = PETSC_TRUE;
9604:     MatProductSetFromOptions(*C);
9606:     MatProductSymbolic(*C);
9607:   } else { /* scall == MAT_REUSE_MATRIX */
9608:     MatProductReplaceMats(A, R, NULL, *C);
9609:   }

9611:   MatProductNumeric(*C);
9612:   if (A->symmetric == PETSC_BOOL3_TRUE) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9613:   return 0;
9614: }

9616: static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9617: {

9620:   if (scall == MAT_INITIAL_MATRIX) {
9621:     PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]);
9622:     MatProductCreate(A, B, NULL, C);
9623:     MatProductSetType(*C, ptype);
9624:     MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT);
9625:     MatProductSetFill(*C, fill);

9627:     (*C)->product->api_user = PETSC_TRUE;
9628:     MatProductSetFromOptions(*C);
9629:     MatProductSymbolic(*C);
9630:   } else { /* scall == MAT_REUSE_MATRIX */
9631:     Mat_Product *product = (*C)->product;
9632:     PetscBool    isdense;

9634:     PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "");
9635:     if (isdense && product && product->type != ptype) {
9636:       MatProductClear(*C);
9637:       product = NULL;
9638:     }
9639:     PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]);
9640:     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9641:       if (isdense) {
9642:         MatProductCreate_Private(A, B, NULL, *C);
9643:         product           = (*C)->product;
9644:         product->fill     = fill;
9645:         product->api_user = PETSC_TRUE;
9646:         product->clear    = PETSC_TRUE;

9648:         MatProductSetType(*C, ptype);
9649:         MatProductSetFromOptions(*C);
9651:         MatProductSymbolic(*C);
9652:       } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9653:     } else { /* user may change input matrices A or B when REUSE */
9654:       MatProductReplaceMats(A, B, NULL, *C);
9655:     }
9656:   }
9657:   MatProductNumeric(*C);
9658:   return 0;
9659: }

9661: /*@
9662:    MatMatMult - Performs matrix-matrix multiplication C=A*B.

9664:    Neighbor-wise Collective on A

9666:    Input Parameters:
9667: +  A - the left matrix
9668: .  B - the right matrix
9669: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9670: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9671:           if the result is a dense matrix this is irrelevant

9673:    Output Parameters:
9674: .  C - the product matrix

9676:    Notes:
9677:    Unless scall is `MAT_REUSE_MATRIX` C will be created.

9679:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call and C was obtained from a previous
9680:    call to this function with `MAT_INITIAL_MATRIX`.

9682:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.

9684:    In the special case where matrix B (and hence C) are dense you can create the correctly sized matrix C yourself and then call this routine with `MAT_REUSE_MATRIX`,
9685:    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.

9687:    Example of Usage:
9688: .vb
9689:      MatProductCreate(A,B,NULL,&C);
9690:      MatProductSetType(C,MATPRODUCT_AB);
9691:      MatProductSymbolic(C);
9692:      MatProductNumeric(C); // compute C=A * B
9693:      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9694:      MatProductNumeric(C);
9695:      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9696:      MatProductNumeric(C);
9697: .ve

9699:    Level: intermediate

9701: .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9702: @*/
9703: PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9704: {
9705:   MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C);
9706:   return 0;
9707: }

9709: /*@
9710:    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.

9712:    Neighbor-wise Collective on A

9714:    Input Parameters:
9715: +  A - the left matrix
9716: .  B - the right matrix
9717: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9718: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known

9720:    Output Parameters:
9721: .  C - the product matrix

9723:    Notes:
9724:    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.

9726:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call

9728:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9729:    actually needed.

9731:    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9732:    and for pairs of `MATMPIDENSE` matrices.

9734:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`

9736:    Options Database Keys:
9737: .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9738:               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9739:               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.

9741:    Level: intermediate

9743: .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9744: @*/
9745: PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9746: {
9747:   MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C);
9748:   if (A == B) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9749:   return 0;
9750: }

9752: /*@
9753:    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.

9755:    Neighbor-wise Collective on A

9757:    Input Parameters:
9758: +  A - the left matrix
9759: .  B - the right matrix
9760: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9761: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known

9763:    Output Parameters:
9764: .  C - the product matrix

9766:    Notes:
9767:    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.

9769:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.

9771:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`

9773:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9774:    actually needed.

9776:    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9777:    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.

9779:    Level: intermediate

9781: .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9782: @*/
9783: PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9784: {
9785:   MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C);
9786:   return 0;
9787: }

9789: /*@
9790:    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.

9792:    Neighbor-wise Collective on A

9794:    Input Parameters:
9795: +  A - the left matrix
9796: .  B - the middle matrix
9797: .  C - the right matrix
9798: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9799: -  fill - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DEFAULT` if you do not have a good estimate
9800:           if the result is a dense matrix this is irrelevant

9802:    Output Parameters:
9803: .  D - the product matrix

9805:    Notes:
9806:    Unless scall is `MAT_REUSE_MATRIX` D will be created.

9808:    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call

9810:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`

9812:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9813:    actually needed.

9815:    If you have many matrices with the same non-zero structure to multiply, you
9816:    should use `MAT_REUSE_MATRIX` in all calls but the first

9818:    Level: intermediate

9820: .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9821: @*/
9822: PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
9823: {
9824:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);

9827:   if (scall == MAT_INITIAL_MATRIX) {
9828:     MatProductCreate(A, B, C, D);
9829:     MatProductSetType(*D, MATPRODUCT_ABC);
9830:     MatProductSetAlgorithm(*D, "default");
9831:     MatProductSetFill(*D, fill);

9833:     (*D)->product->api_user = PETSC_TRUE;
9834:     MatProductSetFromOptions(*D);
9836:                ((PetscObject)C)->type_name);
9837:     MatProductSymbolic(*D);
9838:   } else { /* user may change input matrices when REUSE */
9839:     MatProductReplaceMats(A, B, C, *D);
9840:   }
9841:   MatProductNumeric(*D);
9842:   return 0;
9843: }

9845: /*@
9846:    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.

9848:    Collective on mat

9850:    Input Parameters:
9851: +  mat - the matrix
9852: .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9853: .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
9854: -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

9856:    Output Parameter:
9857: .  matredundant - redundant matrix

9859:    Notes:
9860:    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
9861:    original matrix has not changed from that last call to MatCreateRedundantMatrix().

9863:    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9864:    calling it.

9866:    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.

9868:    Level: advanced

9870: .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
9871: @*/
9872: PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
9873: {
9874:   MPI_Comm       comm;
9875:   PetscMPIInt    size;
9876:   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9877:   Mat_Redundant *redund     = NULL;
9878:   PetscSubcomm   psubcomm   = NULL;
9879:   MPI_Comm       subcomm_in = subcomm;
9880:   Mat           *matseq;
9881:   IS             isrow, iscol;
9882:   PetscBool      newsubcomm = PETSC_FALSE;

9885:   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9888:   }

9890:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
9891:   if (size == 1 || nsubcomm == 1) {
9892:     if (reuse == MAT_INITIAL_MATRIX) {
9893:       MatDuplicate(mat, MAT_COPY_VALUES, matredundant);
9894:     } else {
9896:       MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN);
9897:     }
9898:     return 0;
9899:   }

9903:   MatCheckPreallocated(mat, 1);

9905:   PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0);
9906:   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9907:     /* create psubcomm, then get subcomm */
9908:     PetscObjectGetComm((PetscObject)mat, &comm);
9909:     MPI_Comm_size(comm, &size);

9912:     PetscSubcommCreate(comm, &psubcomm);
9913:     PetscSubcommSetNumber(psubcomm, nsubcomm);
9914:     PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS);
9915:     PetscSubcommSetFromOptions(psubcomm);
9916:     PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL);
9917:     newsubcomm = PETSC_TRUE;
9918:     PetscSubcommDestroy(&psubcomm);
9919:   }

9921:   /* get isrow, iscol and a local sequential matrix matseq[0] */
9922:   if (reuse == MAT_INITIAL_MATRIX) {
9923:     mloc_sub = PETSC_DECIDE;
9924:     nloc_sub = PETSC_DECIDE;
9925:     if (bs < 1) {
9926:       PetscSplitOwnership(subcomm, &mloc_sub, &M);
9927:       PetscSplitOwnership(subcomm, &nloc_sub, &N);
9928:     } else {
9929:       PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M);
9930:       PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N);
9931:     }
9932:     MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm);
9933:     rstart = rend - mloc_sub;
9934:     ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow);
9935:     ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol);
9936:   } else { /* reuse == MAT_REUSE_MATRIX */
9938:     /* retrieve subcomm */
9939:     PetscObjectGetComm((PetscObject)(*matredundant), &subcomm);
9940:     redund = (*matredundant)->redundant;
9941:     isrow  = redund->isrow;
9942:     iscol  = redund->iscol;
9943:     matseq = redund->matseq;
9944:   }
9945:   MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq);

9947:   /* get matredundant over subcomm */
9948:   if (reuse == MAT_INITIAL_MATRIX) {
9949:     MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant);

9951:     /* create a supporting struct and attach it to C for reuse */
9952:     PetscNew(&redund);
9953:     (*matredundant)->redundant = redund;
9954:     redund->isrow              = isrow;
9955:     redund->iscol              = iscol;
9956:     redund->matseq             = matseq;
9957:     if (newsubcomm) {
9958:       redund->subcomm = subcomm;
9959:     } else {
9960:       redund->subcomm = MPI_COMM_NULL;
9961:     }
9962:   } else {
9963:     MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant);
9964:   }
9965: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9966:   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
9967:     MatBindToCPU(*matredundant, PETSC_TRUE);
9968:     MatSetBindingPropagates(*matredundant, PETSC_TRUE);
9969:   }
9970: #endif
9971:   PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0);
9972:   return 0;
9973: }

9975: /*@C
9976:    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
9977:    a given `Mat`. Each submatrix can span multiple procs.

9979:    Collective on mat

9981:    Input Parameters:
9982: +  mat - the matrix
9983: .  subcomm - the subcommunicator obtained by MPI_Com_split(comm)
9984: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

9986:    Output Parameter:
9987: .  subMat - 'parallel submatrices each spans a given subcomm

9989:   Notes:
9990:   The submatrix partition across processors is dictated by 'subComm' a
9991:   communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
9992:   is not restriced to be grouped with consecutive original ranks.

9994:   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
9995:   map directly to the layout of the original matrix [wrt the local
9996:   row,col partitioning]. So the original 'DiagonalMat' naturally maps
9997:   into the 'DiagonalMat' of the subMat, hence it is used directly from
9998:   the subMat. However the offDiagMat looses some columns - and this is
9999:   reconstructed with `MatSetValues()`

10001:   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks

10003:   Level: advanced

10005: .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10006: @*/
10007: PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10008: {
10009:   PetscMPIInt commsize, subCommSize;

10011:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize);
10012:   MPI_Comm_size(subComm, &subCommSize);

10016:   PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10017:   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10018:   PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10019:   return 0;
10020: }

10022: /*@
10023:    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering

10025:    Not Collective

10027:    Input Parameters:
10028: +  mat - matrix to extract local submatrix from
10029: .  isrow - local row indices for submatrix
10030: -  iscol - local column indices for submatrix

10032:    Output Parameter:
10033: .  submat - the submatrix

10035:    Level: intermediate

10037:    Notes:
10038:    The submat should be returned with `MatRestoreLocalSubMatrix()`.

10040:    Depending on the format of mat, the returned submat may not implement `MatMult()`.  Its communicator may be
10041:    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.

10043:    The submat always implements `MatSetValuesLocal()`.  If isrow and iscol have the same block size, then
10044:    `MatSetValuesBlockedLocal()` will also be implemented.

10046:    The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10047:    Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.

10049: .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10050: @*/
10051: PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10052: {

10060:   if (mat->ops->getlocalsubmatrix) {
10061:     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10062:   } else {
10063:     MatCreateLocalRef(mat, isrow, iscol, submat);
10064:   }
10065:   return 0;
10066: }

10068: /*@
10069:    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`

10071:    Not Collective

10073:    Input Parameters:
10074: +  mat - matrix to extract local submatrix from
10075: .  isrow - local row indices for submatrix
10076: .  iscol - local column indices for submatrix
10077: -  submat - the submatrix

10079:    Level: intermediate

10081: .seealso: `MatGetLocalSubMatrix()`
10082: @*/
10083: PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10084: {

10092:   if (mat->ops->restorelocalsubmatrix) {
10093:     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10094:   } else {
10095:     MatDestroy(submat);
10096:   }
10097:   *submat = NULL;
10098:   return 0;
10099: }

10101: /* --------------------------------------------------------*/
10102: /*@
10103:    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix

10105:    Collective on mat

10107:    Input Parameter:
10108: .  mat - the matrix

10110:    Output Parameter:
10111: .  is - if any rows have zero diagonals this contains the list of them

10113:    Level: developer

10115: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10116: @*/
10117: PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10118: {

10124:   if (!mat->ops->findzerodiagonals) {
10125:     Vec                diag;
10126:     const PetscScalar *a;
10127:     PetscInt          *rows;
10128:     PetscInt           rStart, rEnd, r, nrow = 0;

10130:     MatCreateVecs(mat, &diag, NULL);
10131:     MatGetDiagonal(mat, diag);
10132:     MatGetOwnershipRange(mat, &rStart, &rEnd);
10133:     VecGetArrayRead(diag, &a);
10134:     for (r = 0; r < rEnd - rStart; ++r)
10135:       if (a[r] == 0.0) ++nrow;
10136:     PetscMalloc1(nrow, &rows);
10137:     nrow = 0;
10138:     for (r = 0; r < rEnd - rStart; ++r)
10139:       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10140:     VecRestoreArrayRead(diag, &a);
10141:     VecDestroy(&diag);
10142:     ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is);
10143:   } else {
10144:     PetscUseTypeMethod(mat, findzerodiagonals, is);
10145:   }
10146:   return 0;
10147: }

10149: /*@
10150:    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)

10152:    Collective on mat

10154:    Input Parameter:
10155: .  mat - the matrix

10157:    Output Parameter:
10158: .  is - contains the list of rows with off block diagonal entries

10160:    Level: developer

10162: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10163: @*/
10164: PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10165: {

10171:   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10172:   return 0;
10173: }

10175: /*@C
10176:   MatInvertBlockDiagonal - Inverts the block diagonal entries.

10178:   Collective on mat

10180:   Input Parameters:
10181: . mat - the matrix

10183:   Output Parameters:
10184: . values - the block inverses in column major order (FORTRAN-like)

10186:    Notes:
10187:    The size of the blocks is determined by the block size of the matrix.

10189:    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case

10191:    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size

10193:    Fortran Note:
10194:      This routine is not available from Fortran.

10196:   Level: advanced

10198: .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10199: @*/
10200: PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10201: {
10205:   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10206:   return 0;
10207: }

10209: /*@C
10210:   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.

10212:   Collective on mat

10214:   Input Parameters:
10215: + mat - the matrix
10216: . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10217: - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`

10219:   Output Parameters:
10220: . values - the block inverses in column major order (FORTRAN-like)

10222:   Notes:
10223:   Use `MatInvertBlockDiagonal()` if all blocks have the same size

10225:   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case

10227:   Fortran Note:
10228:   This routine is not available from Fortran.

10230:   Level: advanced

10232: .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10233: @*/
10234: PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10235: {
10239:   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10240:   return 0;
10241: }

10243: /*@
10244:   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A

10246:   Collective on Mat

10248:   Input Parameters:
10249: + A - the matrix
10250: - C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.

10252:   Note:
10253:   The blocksize of the matrix is used to determine the blocks on the diagonal of C

10255:   Level: advanced

10257: .seealso: `MatInvertBlockDiagonal()`
10258: @*/
10259: PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10260: {
10261:   const PetscScalar *vals;
10262:   PetscInt          *dnnz;
10263:   PetscInt           m, rstart, rend, bs, i, j;

10265:   MatInvertBlockDiagonal(A, &vals);
10266:   MatGetBlockSize(A, &bs);
10267:   MatGetLocalSize(A, &m, NULL);
10268:   MatSetLayouts(C, A->rmap, A->cmap);
10269:   PetscMalloc1(m / bs, &dnnz);
10270:   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10271:   MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL);
10272:   PetscFree(dnnz);
10273:   MatGetOwnershipRange(C, &rstart, &rend);
10274:   MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE);
10275:   for (i = rstart / bs; i < rend / bs; i++) MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES);
10276:   MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY);
10277:   MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY);
10278:   MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE);
10279:   return 0;
10280: }

10282: /*@C
10283:     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10284:     via `MatTransposeColoringCreate()`.

10286:     Collective on c

10288:     Input Parameter:
10289: .   c - coloring context

10291:     Level: intermediate

10293: .seealso: `MatTransposeColoringCreate()`
10294: @*/
10295: PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10296: {
10297:   MatTransposeColoring matcolor = *c;

10299:   if (!matcolor) return 0;
10300:   if (--((PetscObject)matcolor)->refct > 0) {
10301:     matcolor = NULL;
10302:     return 0;
10303:   }

10305:   PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow);
10306:   PetscFree(matcolor->rows);
10307:   PetscFree(matcolor->den2sp);
10308:   PetscFree(matcolor->colorforcol);
10309:   PetscFree(matcolor->columns);
10310:   if (matcolor->brows > 0) PetscFree(matcolor->lstart);
10311:   PetscHeaderDestroy(c);
10312:   return 0;
10313: }

10315: /*@C
10316:     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10317:     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10318:     `MatTransposeColoring` to sparse B.

10320:     Collective on coloring

10322:     Input Parameters:
10323: +   B - sparse matrix B
10324: .   Btdense - symbolic dense matrix B^T
10325: -   coloring - coloring context created with `MatTransposeColoringCreate()`

10327:     Output Parameter:
10328: .   Btdense - dense matrix B^T

10330:     Level: developer

10332:     Note:
10333:     These are used internally for some implementations of `MatRARt()`

10335: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`

10337: @*/
10338: PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10339: {

10344:   (B->ops->transcoloringapplysptoden)(coloring, B, Btdense);
10345:   return 0;
10346: }

10348: /*@C
10349:     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10350:     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10351:     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10352:     Csp from Cden.

10354:     Collective on matcoloring

10356:     Input Parameters:
10357: +   coloring - coloring context created with `MatTransposeColoringCreate()`
10358: -   Cden - matrix product of a sparse matrix and a dense matrix Btdense

10360:     Output Parameter:
10361: .   Csp - sparse matrix

10363:     Level: developer

10365:     Note:
10366:     These are used internally for some implementations of `MatRARt()`

10368: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`

10370: @*/
10371: PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10372: {

10377:   (Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp);
10378:   MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY);
10379:   MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY);
10380:   return 0;
10381: }

10383: /*@C
10384:    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.

10386:    Collective on mat

10388:    Input Parameters:
10389: +  mat - the matrix product C
10390: -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`

10392:     Output Parameter:
10393: .   color - the new coloring context

10395:     Level: intermediate

10397: .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10398:           `MatTransColoringApplyDenToSp()`
10399: @*/
10400: PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10401: {
10402:   MatTransposeColoring c;
10403:   MPI_Comm             comm;

10405:   PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10406:   PetscObjectGetComm((PetscObject)mat, &comm);
10407:   PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL);

10409:   c->ctype = iscoloring->ctype;
10410:   if (mat->ops->transposecoloringcreate) {
10411:     PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10412:   } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);

10414:   *color = c;
10415:   PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10416:   return 0;
10417: }

10419: /*@
10420:       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10421:         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10422:         same, otherwise it will be larger

10424:      Not Collective

10426:   Input Parameter:
10427: .    A  - the matrix

10429:   Output Parameter:
10430: .    state - the current state

10432:   Notes:
10433:     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10434:          different matrices

10436:     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix

10438:     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.

10440:   Level: intermediate

10442: .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10443: @*/
10444: PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10445: {
10447:   *state = mat->nonzerostate;
10448:   return 0;
10449: }

10451: /*@
10452:       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10453:                  matrices from each processor

10455:     Collective

10457:    Input Parameters:
10458: +    comm - the communicators the parallel matrix will live on
10459: .    seqmat - the input sequential matrices
10460: .    n - number of local columns (or `PETSC_DECIDE`)
10461: -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

10463:    Output Parameter:
10464: .    mpimat - the parallel matrix generated

10466:     Level: developer

10468:    Note:
10469:     The number of columns of the matrix in EACH processor MUST be the same.

10471: .seealso: `Mat`
10472: @*/
10473: PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10474: {
10475:   PetscMPIInt size;

10477:   MPI_Comm_size(comm, &size);
10478:   if (size == 1) {
10479:     if (reuse == MAT_INITIAL_MATRIX) {
10480:       MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat);
10481:     } else {
10482:       MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN);
10483:     }
10484:     return 0;
10485:   }


10489:   PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0);
10490:   (*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat);
10491:   PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0);
10492:   return 0;
10493: }

10495: /*@
10496:      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.

10498:     Collective on A

10500:    Input Parameters:
10501: +    A   - the matrix to create subdomains from
10502: -    N   - requested number of subdomains

10504:    Output Parameters:
10505: +    n   - number of subdomains resulting on this rank
10506: -    iss - `IS` list with indices of subdomains on this rank

10508:     Level: advanced

10510:     Note:
10511:     The number of subdomains must be smaller than the communicator size

10513: .seealso: `Mat`, `IS`
10514: @*/
10515: PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10516: {
10517:   MPI_Comm    comm, subcomm;
10518:   PetscMPIInt size, rank, color;
10519:   PetscInt    rstart, rend, k;

10521:   PetscObjectGetComm((PetscObject)A, &comm);
10522:   MPI_Comm_size(comm, &size);
10523:   MPI_Comm_rank(comm, &rank);
10525:   *n    = 1;
10526:   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10527:   color = rank / k;
10528:   MPI_Comm_split(comm, color, rank, &subcomm);
10529:   PetscMalloc1(1, iss);
10530:   MatGetOwnershipRange(A, &rstart, &rend);
10531:   ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]);
10532:   MPI_Comm_free(&subcomm);
10533:   return 0;
10534: }

10536: /*@
10537:    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.

10539:    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10540:    If they are not the same, uses `MatMatMatMult()`.

10542:    Once the coarse grid problem is constructed, correct for interpolation operators
10543:    that are not of full rank, which can legitimately happen in the case of non-nested
10544:    geometric multigrid.

10546:    Input Parameters:
10547: +  restrct - restriction operator
10548: .  dA - fine grid matrix
10549: .  interpolate - interpolation operator
10550: .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10551: -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate

10553:    Output Parameters:
10554: .  A - the Galerkin coarse matrix

10556:    Options Database Key:
10557: .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used

10559:    Level: developer

10561: .seealso: `MatPtAP()`, `MatMatMatMult()`
10562: @*/
10563: PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10564: {
10565:   IS  zerorows;
10566:   Vec diag;

10569:   /* Construct the coarse grid matrix */
10570:   if (interpolate == restrct) {
10571:     MatPtAP(dA, interpolate, reuse, fill, A);
10572:   } else {
10573:     MatMatMatMult(restrct, dA, interpolate, reuse, fill, A);
10574:   }

10576:   /* If the interpolation matrix is not of full rank, A will have zero rows.
10577:      This can legitimately happen in the case of non-nested geometric multigrid.
10578:      In that event, we set the rows of the matrix to the rows of the identity,
10579:      ignoring the equations (as the RHS will also be zero). */

10581:   MatFindZeroRows(*A, &zerorows);

10583:   if (zerorows != NULL) { /* if there are any zero rows */
10584:     MatCreateVecs(*A, &diag, NULL);
10585:     MatGetDiagonal(*A, diag);
10586:     VecISSet(diag, zerorows, 1.0);
10587:     MatDiagonalSet(*A, diag, INSERT_VALUES);
10588:     VecDestroy(&diag);
10589:     ISDestroy(&zerorows);
10590:   }
10591:   return 0;
10592: }

10594: /*@C
10595:     MatSetOperation - Allows user to set a matrix operation for any matrix type

10597:    Logically Collective on mat

10599:     Input Parameters:
10600: +   mat - the matrix
10601: .   op - the name of the operation
10602: -   f - the function that provides the operation

10604:    Level: developer

10606:     Usage:
10607: $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10608: $      MatCreateXXX(comm,...&A;
10609: $      MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult;

10611:     Notes:
10612:     See the file include/petscmat.h for a complete list of matrix
10613:     operations, which all have the form MATOP_<OPERATION>, where
10614:     <OPERATION> is the name (in all capital letters) of the
10615:     user interface routine (e.g., MatMult() -> MATOP_MULT).

10617:     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10618:     sequence as the usual matrix interface routines, since they
10619:     are intended to be accessed via the usual matrix interface
10620:     routines, e.g.,
10621: $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)

10623:     In particular each function MUST return an error code of 0 on success and
10624:     nonzero on failure.

10626:     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.

10628: .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10629: @*/
10630: PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10631: {
10633:   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10634:   (((void (**)(void))mat->ops)[op]) = f;
10635:   return 0;
10636: }

10638: /*@C
10639:     MatGetOperation - Gets a matrix operation for any matrix type.

10641:     Not Collective

10643:     Input Parameters:
10644: +   mat - the matrix
10645: -   op - the name of the operation

10647:     Output Parameter:
10648: .   f - the function that provides the operation

10650:     Level: developer

10652:     Usage:
10653: $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10654: $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);

10656:     Notes:
10657:     See the file include/petscmat.h for a complete list of matrix
10658:     operations, which all have the form MATOP_<OPERATION>, where
10659:     <OPERATION> is the name (in all capital letters) of the
10660:     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).

10662:     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.

10664: .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10665: @*/
10666: PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10667: {
10669:   *f = (((void (**)(void))mat->ops)[op]);
10670:   return 0;
10671: }

10673: /*@
10674:     MatHasOperation - Determines whether the given matrix supports the particular operation.

10676:    Not Collective

10678:    Input Parameters:
10679: +  mat - the matrix
10680: -  op - the operation, for example, `MATOP_GET_DIAGONAL`

10682:    Output Parameter:
10683: .  has - either `PETSC_TRUE` or `PETSC_FALSE`

10685:    Level: advanced

10687:    Note:
10688:    See the file include/petscmat.h for a complete list of matrix
10689:    operations, which all have the form MATOP_<OPERATION>, where
10690:    <OPERATION> is the name (in all capital letters) of the
10691:    user-level routine.  E.g., `MatNorm()` -> `MATOP_NORM`.

10693: .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10694: @*/
10695: PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10696: {
10699:   if (mat->ops->hasoperation) {
10700:     PetscUseTypeMethod(mat, hasoperation, op, has);
10701:   } else {
10702:     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10703:     else {
10704:       *has = PETSC_FALSE;
10705:       if (op == MATOP_CREATE_SUBMATRIX) {
10706:         PetscMPIInt size;

10708:         MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
10709:         if (size == 1) MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has);
10710:       }
10711:     }
10712:   }
10713:   return 0;
10714: }

10716: /*@
10717:     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent

10719:    Collective on mat

10721:    Input Parameters:
10722: .  mat - the matrix

10724:    Output Parameter:
10725: .  cong - either `PETSC_TRUE` or `PETSC_FALSE`

10727:    Level: beginner

10729: .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10730: @*/
10731: PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10732: {
10736:   if (!mat->rmap || !mat->cmap) {
10737:     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10738:     return 0;
10739:   }
10740:   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10741:     PetscLayoutSetUp(mat->rmap);
10742:     PetscLayoutSetUp(mat->cmap);
10743:     PetscLayoutCompare(mat->rmap, mat->cmap, cong);
10744:     if (*cong) mat->congruentlayouts = 1;
10745:     else mat->congruentlayouts = 0;
10746:   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10747:   return 0;
10748: }

10750: PetscErrorCode MatSetInf(Mat A)
10751: {
10752:   PetscUseTypeMethod(A, setinf);
10753:   return 0;
10754: }

10756: /*C
10757:    MatCreateGraph - create a scalar matrix (that is a matrix with one vertex for each block vertex in the original matrix), for use in graph algorithms
10758:    and possibly removes small values from the graph structure.

10760:    Collective on mat

10762:    Input Parameters:
10763: +  A - the matrix
10764: .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
10765: .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
10766: -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value

10768:    Output Parameter:
10769: .  graph - the resulting graph

10771:    Level: advanced

10773: .seealso: `MatCreate()`, `PCGAMG`
10774: */
10775: PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
10776: {
10780:   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
10781:   return 0;
10782: }