Actual source code: matrix.c

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

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

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

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

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

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

 54:    Logically Collective on mat

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

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

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

 71:    Level: intermediate

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

 82:   MatCheckPreallocated(x, 1);

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

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

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

105:    Logically Collective on mat

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

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

115:    Level: advanced

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

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

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

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

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

140:    Logically Collective on mat

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

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

148:    Level: advanced

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

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

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

167:    Logically Collective on mat

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

172:    Level: developer

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

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

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

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

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

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

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

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

255:   Level: intermediate

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

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

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

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

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

283:   Level: intermediate

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

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

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

312:    Not Collective

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

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

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

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

325:    Level: advanced

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

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

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

349:    Collective on mat

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

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

357:    Level: advanced

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

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

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

377:    Logically Collective on mat

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

382:    Level: advanced

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

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

400:    Collective on mat

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

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

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

412:    Level: advanced

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

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

433:    Logically Collective on mat

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

438:    Level: advanced

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

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

456:    Not Collective

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

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

465:    Level: advanced

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

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

485:    Not Collective

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

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

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

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

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

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

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

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

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

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

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

538:    Level: advanced

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

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

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

562:    Logically Collective on mat

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

567:    Level: advanced

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

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

585:    Not Collective

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

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

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

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

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

615:    Level: advanced

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

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

636:    Not Collective

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

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

644:    Level: advanced

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

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

663:    Not Collective

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

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

671:    Level: advanced

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

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

691:    Logically Collective on A

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

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

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

705:    Level: advanced

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

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

720:    Logically Collective on A

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

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

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

733:    Level: developer

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

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

755:    Logically Collective on A

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

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

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

768:    Level: developer

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

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

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

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

800:    Logically Collective on A

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

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

810:    Level: advanced

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

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

825:    Not Collective

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

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

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

837:    Level: advanced

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

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

852:    Collective on A

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

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

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

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

864:    Level: beginner

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

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

879:    Collective on A

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

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

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

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

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

893:    Level: intermediate

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

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

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

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

923:    Collective on A

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

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

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

945:    Level: intermediate

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

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

959:    Collective on mat

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

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

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

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

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

1011:    Level: beginner

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

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

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

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

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

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

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

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

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

1058:   PetscLogEventBegin(MAT_View, mat, viewer, 0, 0);
1059:   if (isascii) {
1060:     if (!mat->preallocated) {
1061:       PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n");
1062:       return 0;
1063:     }
1064:     if (!mat->assembled) {
1065:       PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n");
1066:       return 0;
1067:     }
1068:     PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer);
1069:     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1070:       MatNullSpace nullsp, transnullsp;

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

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

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

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

1150:    Collective on mat

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

1157:    Options Database Keys:
1158:    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1159:    block size
1160: .    -matload_block_size <bs> - set block size

1162:    Level: beginner

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

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

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

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

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

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

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

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

1213: $    PetscInt    MAT_FILE_CLASSID
1214: $    PetscInt    number of rows
1215: $    PetscInt    number of columns
1216: $    PetscInt    total number of nonzeros
1217: $    PetscInt    *number nonzeros in each row
1218: $    PetscInt    *column indices of all nonzeros (starting index is zero)
1219: $    PetscScalar *values of all nonzeros

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

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

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

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

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

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

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

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

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

1260: .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1261:  @*/
1262: PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1263: {
1264:   PetscBool flg;


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

1271:   flg = PETSC_FALSE;
1272:   PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL);
1273:   if (flg) {
1274:     MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE);
1275:     MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE);
1276:   }
1277:   flg = PETSC_FALSE;
1278:   PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL);
1279:   if (flg) MatSetOption(mat, MAT_SPD, PETSC_TRUE);

1281:   PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0);
1282:   PetscUseTypeMethod(mat, load, viewer);
1283:   PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0);
1284:   return 0;
1285: }

1287: static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1288: {
1289:   Mat_Redundant *redund = *redundant;

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

1307:     if (redund->subcomm) PetscCommDestroy(&redund->subcomm);
1308:     PetscFree(redund);
1309:   }
1310:   return 0;
1311: }

1313: /*@C
1314:    MatDestroy - Frees space taken by a matrix.

1316:    Collective on A

1318:    Input Parameter:
1319: .  A - the matrix

1321:    Level: beginner

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

1329: .seealso: `Mat`, `MatCreate()`
1330: @*/
1331: PetscErrorCode MatDestroy(Mat *A)
1332: {
1333:   if (!*A) return 0;
1335:   if (--((PetscObject)(*A))->refct > 0) {
1336:     *A = NULL;
1337:     return 0;
1338:   }

1340:   /* if memory was published with SAWs then destroy it */
1341:   PetscObjectSAWsViewOff((PetscObject)*A);
1342:   PetscTryTypeMethod((*A), destroy);

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

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

1368:    Not Collective

1370:    Input Parameters:
1371: +  mat - the matrix
1372: .  v - a logically two-dimensional array of values
1373: .  m, idxm - the number of rows and their global indices
1374: .  n, idxn - the number of columns and their global indices
1375: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

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

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

1383:    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1384:    options cannot be mixed without intervening calls to the assembly
1385:    routines.

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

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

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

1399:    Level: beginner

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

1405: .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1406:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1407: @*/
1408: PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1409: {
1413:   if (!m || !n) return 0; /* no values to insert */
1416:   MatCheckPreallocated(mat, 1);

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

1421:   if (PetscDefined(USE_DEBUG)) {
1422:     PetscInt i, j;

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

1439:   if (mat->assembled) {
1440:     mat->was_assembled = PETSC_TRUE;
1441:     mat->assembled     = PETSC_FALSE;
1442:   }
1443:   PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1444:   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1445:   PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1446:   return 0;
1447: }

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

1454:    Not Collective

1456:    Input Parameters:
1457: +  mat - the matrix
1458: .  v - a logically two-dimensional array of values
1459: .  ism - the rows to provide
1460: .  isn - the columns to provide
1461: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

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

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

1469:    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1470:    options cannot be mixed without intervening calls to the assembly
1471:    routines.

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

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

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

1485:    Level: beginner

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

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

1493: .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1494:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1495: @*/
1496: PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1497: {
1498:   PetscInt        m, n;
1499:   const PetscInt *rows, *cols;

1503:   ISGetIndices(ism, &rows);
1504:   ISGetIndices(isn, &cols);
1505:   ISGetLocalSize(ism, &m);
1506:   ISGetLocalSize(isn, &n);
1507:   MatSetValues(mat, m, rows, n, cols, v, addv);
1508:   ISRestoreIndices(ism, &rows);
1509:   ISRestoreIndices(isn, &cols);
1510:   return 0;
1511: }

1513: /*@
1514:    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1515:         values into a matrix

1517:    Not Collective

1519:    Input Parameters:
1520: +  mat - the matrix
1521: .  row - the (block) row to set
1522: -  v - a logically two-dimensional array of values

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

1527:    All the nonzeros in the row must be provided

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

1531:    The row must belong to this process

1533:    Level: intermediate

1535: .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1536:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1537: @*/
1538: PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1539: {
1540:   PetscInt globalrow;

1545:   ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow);
1546:   MatSetValuesRow(mat, globalrow, v);
1547:   return 0;
1548: }

1550: /*@
1551:    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1552:         values into a matrix

1554:    Not Collective

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

1561:    Notes:
1562:    The values, v, are column-oriented for the block version.

1564:    All the nonzeros in the row must be provided

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

1568:    The row must belong to this process

1570:    Level: advanced

1572: .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1573:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1574: @*/
1575: PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1576: {
1580:   MatCheckPreallocated(mat, 1);
1584:   mat->insertmode = INSERT_VALUES;

1586:   if (mat->assembled) {
1587:     mat->was_assembled = PETSC_TRUE;
1588:     mat->assembled     = PETSC_FALSE;
1589:   }
1590:   PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1591:   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1592:   PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1593:   return 0;
1594: }

1596: /*@
1597:    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1598:      Using structured grid indexing

1600:    Not Collective

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

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

1614:    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1615:    options cannot be mixed without intervening calls to the assembly
1616:    routines.

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

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

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

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

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

1634:    In Fortran idxm and idxn should be declared as
1635: $     MatStencil idxm(4,m),idxn(4,n)
1636:    and the values inserted using
1637: $    idxm(MatStencil_i,1) = i
1638: $    idxm(MatStencil_j,1) = j
1639: $    idxm(MatStencil_k,1) = k
1640: $    idxm(MatStencil_c,1) = c
1641:    etc

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

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

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

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

1658:    Level: beginner

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

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

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

1708: /*@
1709:    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1710:      Using structured grid indexing

1712:    Not Collective

1714:    Input Parameters:
1715: +  mat - the matrix
1716: .  m - number of rows being entered
1717: .  idxm - grid coordinates for matrix rows being entered
1718: .  n - number of columns being entered
1719: .  idxn - grid coordinates for matrix columns being entered
1720: .  v - a logically two-dimensional array of values
1721: -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values

1723:    Notes:
1724:    By default the values, v, are row-oriented and unsorted.
1725:    See `MatSetOption()` for other options.

1727:    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1728:    options cannot be mixed without intervening calls to the assembly
1729:    routines.

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

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

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

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

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

1747:    In Fortran idxm and idxn should be declared as
1748: $     MatStencil idxm(4,m),idxn(4,n)
1749:    and the values inserted using
1750: $    idxm(MatStencil_i,1) = i
1751: $    idxm(MatStencil_j,1) = j
1752: $    idxm(MatStencil_k,1) = k
1753:    etc

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

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

1763:    Level: beginner

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

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

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

1815: /*@
1816:    MatSetStencil - Sets the grid information for setting values into a matrix via
1817:         `MatSetValuesStencil()`

1819:    Not Collective

1821:    Input Parameters:
1822: +  mat - the matrix
1823: .  dim - dimension of the grid 1, 2, or 3
1824: .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1825: .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1826: -  dof - number of degrees of freedom per node

1828:    Notes:
1829:    Inspired by the structured grid interface to the HYPRE package
1830:    (www.llnl.gov/CASC/hyper)

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

1835:    Level: beginner

1837: .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1838:           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1839: @*/
1840: PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1841: {

1846:   mat->stencil.dim = dim + (dof > 1);
1847:   for (PetscInt i = 0; i < dim; i++) {
1848:     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1849:     mat->stencil.starts[i] = starts[dim - i - 1];
1850:   }
1851:   mat->stencil.dims[dim]   = dof;
1852:   mat->stencil.starts[dim] = 0;
1853:   mat->stencil.noc         = (PetscBool)(dof == 1);
1854:   return 0;
1855: }

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

1860:    Not Collective

1862:    Input Parameters:
1863: +  mat - the matrix
1864: .  v - a logically two-dimensional array of values
1865: .  m, idxm - the number of block rows and their global block indices
1866: .  n, idxn - the number of block columns and their global block indices
1867: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values

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

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

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

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

1885:    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1886:    options cannot be mixed without intervening calls to the assembly
1887:    routines.

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

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

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

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

1918:    Level: intermediate

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

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

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

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

1984:    Input Parameters:
1985: +  mat - the matrix
1986: .  v - a logically two-dimensional array for storing the values
1987: .  m, idxm - the number of rows and their global indices
1988: -  n, idxn - the number of columns and their global indices

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

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

1998:      `MatGetValues()` requires that the matrix has been assembled
1999:      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2000:      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2001:      without intermediate matrix assembly.

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

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

2010:    Level: advanced

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

2026:   PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2027:   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2028:   PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2029:   return 0;
2030: }

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

2036:    Not Collective

2038:    Input Parameters:
2039: +  mat - the matrix
2040: .  nrow, irow - number of rows and their local indices
2041: -  ncol, icol - number of columns and their local indices

2043:    Output Parameter:
2044: .  y -  a logically two-dimensional array of values

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

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

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

2058:    Level: advanced

2060: .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2061:           `MatSetValuesLocal()`, `MatGetValues()`
2062: @*/
2063: PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2064: {
2068:   MatCheckPreallocated(mat, 1);
2069:   if (!nrow || !ncol) return 0; /* no values to retrieve */
2072:   if (PetscDefined(USE_DEBUG)) {
2075:   }
2077:   PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2078:   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2079:   else {
2080:     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2081:     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2082:       irowm = buf;
2083:       icolm = buf + nrow;
2084:     } else {
2085:       PetscMalloc2(nrow, &bufr, ncol, &bufc);
2086:       irowm = bufr;
2087:       icolm = bufc;
2088:     }
2091:     ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm);
2092:     ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm);
2093:     MatGetValues(mat, nrow, irowm, ncol, icolm, y);
2094:     PetscFree2(bufr, bufc);
2095:   }
2096:   PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2097:   return 0;
2098: }

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

2104:   Not Collective

2106:   Input Parameters:
2107: + mat - the matrix
2108: . nb - the number of blocks
2109: . bs - the number of rows (and columns) in each block
2110: . rows - a concatenation of the rows for each block
2111: - v - a concatenation of logically two-dimensional arrays of values

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

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

2118:   Level: advanced

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

2131:   PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0);
2132:   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2133:   else {
2134:     for (PetscInt b = 0; b < nb; ++b) MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES);
2135:   }
2136:   PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0);
2137:   return 0;
2138: }

2140: /*@
2141:    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2142:    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2143:    using a local (per-processor) numbering.

2145:    Not Collective

2147:    Input Parameters:
2148: +  x - the matrix
2149: .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2150: -  cmapping - column mapping

2152:    Level: intermediate

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

2157: .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2158: @*/
2159: PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2160: {
2165:   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2166:   else {
2167:     PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping);
2168:     PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping);
2169:   }
2170:   return 0;
2171: }

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

2176:    Not Collective

2178:    Input Parameter:
2179: .  A - the matrix

2181:    Output Parameters:
2182: + rmapping - row mapping
2183: - cmapping - column mapping

2185:    Level: advanced

2187: .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2188: @*/
2189: PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2190: {
2193:   if (rmapping) {
2195:     *rmapping = A->rmap->mapping;
2196:   }
2197:   if (cmapping) {
2199:     *cmapping = A->cmap->mapping;
2200:   }
2201:   return 0;
2202: }

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

2207:    Logically Collective on A

2209:    Input Parameters:
2210: +  A - the matrix
2211: . rmap - row layout
2212: - cmap - column layout

2214:    Level: advanced

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

2219: .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2220: @*/
2221: PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2222: {
2224:   PetscLayoutReference(rmap, &A->rmap);
2225:   PetscLayoutReference(cmap, &A->cmap);
2226:   return 0;
2227: }

2229: /*@
2230:    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns

2232:    Not Collective

2234:    Input Parameter:
2235: .  A - the matrix

2237:    Output Parameters:
2238: + rmap - row layout
2239: - cmap - column layout

2241:    Level: advanced

2243: .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2244: @*/
2245: PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2246: {
2249:   if (rmap) {
2251:     *rmap = A->rmap;
2252:   }
2253:   if (cmap) {
2255:     *cmap = A->cmap;
2256:   }
2257:   return 0;
2258: }

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

2264:    Not Collective

2266:    Input Parameters:
2267: +  mat - the matrix
2268: .  nrow, irow - number of rows and their local indices
2269: .  ncol, icol - number of columns and their local indices
2270: .  y -  a logically two-dimensional array of values
2271: -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

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

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

2279:    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2280:    options cannot be mixed without intervening calls to the assembly
2281:    routines.

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

2286:    Level: intermediate

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

2292: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2293:           `MatGetValuesLocal()`
2294: @*/
2295: PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2296: {
2300:   MatCheckPreallocated(mat, 1);
2301:   if (!nrow || !ncol) return 0; /* no values to insert */
2304:   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2306:   if (PetscDefined(USE_DEBUG)) {
2309:   }

2311:   if (mat->assembled) {
2312:     mat->was_assembled = PETSC_TRUE;
2313:     mat->assembled     = PETSC_FALSE;
2314:   }
2315:   PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2316:   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2317:   else {
2318:     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2319:     const PetscInt *irowm, *icolm;

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

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

2349:    Not Collective

2351:    Input Parameters:
2352: +  x - the matrix
2353: .  nrow, irow - number of rows and their local indices
2354: .  ncol, icol - number of columns and their local indices
2355: .  y -  a logically two-dimensional array of values
2356: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

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

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

2365:    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2366:    options cannot be mixed without intervening calls to the assembly
2367:    routines.

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

2372:    Level: intermediate

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

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

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

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

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

2446:    Collective on mat

2448:    Input Parameters:
2449: +  mat - the matrix
2450: -  x   - the vector to be multiplied

2452:    Output Parameters:
2453: .  y - the result

2455:    Note:
2456:    The vectors x and y cannot be the same.  I.e., one cannot
2457:    call `MatMultDiagonalBlock`(A,y,y).

2459:    Level: developer

2461: .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2462: @*/
2463: PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2464: {

2473:   MatCheckPreallocated(mat, 1);

2475:   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2476:   PetscObjectStateIncrease((PetscObject)y);
2477:   return 0;
2478: }

2480: /* --------------------------------------------------------*/
2481: /*@
2482:    MatMult - Computes the matrix-vector product, y = Ax.

2484:    Neighbor-wise Collective on mat

2486:    Input Parameters:
2487: +  mat - the matrix
2488: -  x   - the vector to be multiplied

2490:    Output Parameters:
2491: .  y - the result

2493:    Note:
2494:    The vectors x and y cannot be the same.  I.e., one cannot
2495:    call `MatMult`(A,y,y).

2497:    Level: beginner

2499: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2500: @*/
2501: PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2502: {
2514:   VecSetErrorIfLocked(y, 3);
2515:   if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2516:   MatCheckPreallocated(mat, 1);

2518:   VecLockReadPush(x);
2519:   PetscLogEventBegin(MAT_Mult, mat, x, y, 0);
2520:   PetscUseTypeMethod(mat, mult, x, y);
2521:   PetscLogEventEnd(MAT_Mult, mat, x, y, 0);
2522:   if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2523:   VecLockReadPop(x);
2524:   return 0;
2525: }

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

2530:    Neighbor-wise Collective on mat

2532:    Input Parameters:
2533: +  mat - the matrix
2534: -  x   - the vector to be multiplied

2536:    Output Parameters:
2537: .  y - the result

2539:    Notes:
2540:    The vectors x and y cannot be the same.  I.e., one cannot
2541:    call `MatMultTranspose`(A,y,y).

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

2546:    Level: beginner

2548: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2549: @*/
2550: PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2551: {
2552:   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;


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

2569:   if (!mat->ops->multtranspose) {
2570:     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2572:   } else op = mat->ops->multtranspose;
2573:   PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0);
2574:   VecLockReadPush(x);
2575:   (*op)(mat, x, y);
2576:   VecLockReadPop(x);
2577:   PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0);
2578:   PetscObjectStateIncrease((PetscObject)y);
2579:   if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2580:   return 0;
2581: }

2583: /*@
2584:    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.

2586:    Neighbor-wise Collective on mat

2588:    Input Parameters:
2589: +  mat - the matrix
2590: -  x   - the vector to be multilplied

2592:    Output Parameters:
2593: .  y - the result

2595:    Notes:
2596:    The vectors x and y cannot be the same.  I.e., one cannot
2597:    call `MatMultHermitianTranspose`(A,y,y).

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

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

2603:    Level: beginner

2605: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2606: @*/
2607: PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2608: {

2621:   MatCheckPreallocated(mat, 1);

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

2647: /*@
2648:     MatMultAdd -  Computes v3 = v2 + A * v1.

2650:     Neighbor-wise Collective on mat

2652:     Input Parameters:
2653: +   mat - the matrix
2654: -   v1, v2 - the vectors

2656:     Output Parameters:
2657: .   v3 - the result

2659:     Note:
2660:     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2661:     call `MatMultAdd`(A,v1,v2,v1).

2663:     Level: beginner

2665: .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2666: @*/
2667: PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2668: {

2683:   MatCheckPreallocated(mat, 1);

2685:   PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3);
2686:   VecLockReadPush(v1);
2687:   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2688:   VecLockReadPop(v1);
2689:   PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3);
2690:   PetscObjectStateIncrease((PetscObject)v3);
2691:   return 0;
2692: }

2694: /*@
2695:    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.

2697:    Neighbor-wise Collective on mat

2699:    Input Parameters:
2700: +  mat - the matrix
2701: -  v1, v2 - the vectors

2703:    Output Parameters:
2704: .  v3 - the result

2706:    Note:
2707:    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2708:    call `MatMultTransposeAdd`(A,v1,v2,v1).

2710:    Level: beginner

2712: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2713: @*/
2714: PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2715: {
2716:   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;


2731:   MatCheckPreallocated(mat, 1);

2733:   PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3);
2734:   VecLockReadPush(v1);
2735:   (*op)(mat, v1, v2, v3);
2736:   VecLockReadPop(v1);
2737:   PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3);
2738:   PetscObjectStateIncrease((PetscObject)v3);
2739:   return 0;
2740: }

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

2745:    Neighbor-wise Collective on mat

2747:    Input Parameters:
2748: +  mat - the matrix
2749: -  v1, v2 - the vectors

2751:    Output Parameters:
2752: .  v3 - the result

2754:    Note:
2755:    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2756:    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).

2758:    Level: beginner

2760: .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2761: @*/
2762: PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2763: {

2776:   MatCheckPreallocated(mat, 1);

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

2803: /*@C
2804:    MatGetFactorType - gets the type of factorization it is

2806:    Not Collective

2808:    Input Parameters:
2809: .  mat - the matrix

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

2814:    Level: intermediate

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

2828: /*@C
2829:    MatSetFactorType - sets the type of factorization it is

2831:    Logically Collective on mat

2833:    Input Parameters:
2834: +  mat - the matrix
2835: -  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`

2837:    Level: intermediate

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

2850: /* ------------------------------------------------------------*/
2851: /*@C
2852:    MatGetInfo - Returns information about matrix storage (number of
2853:    nonzeros, memory, etc.).

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

2857:    Input Parameter:
2858: .  mat - the matrix

2860:    Output Parameters:
2861: +  flag - flag indicating the type of parameters to be returned
2862:    (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors,
2863:    MAT_GLOBAL_SUM - sum over all processors)
2864: -  info - matrix information context

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

2875:    Example for C/C++ Users:
2876:    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2877:    data within the MatInfo context.  For example,
2878: .vb
2879:       MatInfo info;
2880:       Mat     A;
2881:       double  mal, nz_a, nz_u;

2883:       MatGetInfo(A,MAT_LOCAL,&info);
2884:       mal  = info.mallocs;
2885:       nz_a = info.nz_allocated;
2886: .ve

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

2899:       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2900:       mal = info(MAT_INFO_MALLOCS)
2901:       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2902: .ve

2904:     Level: intermediate

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

2909: .seealso: `MatInfo`, `MatStashGetInfo()`
2910: @*/
2911: PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2912: {
2916:   MatCheckPreallocated(mat, 1);
2917:   PetscUseTypeMethod(mat, getinfo, flag, info);
2918:   return 0;
2919: }

2921: /*
2922:    This is used by external packages where it is not easy to get the info from the actual
2923:    matrix factorization.
2924: */
2925: PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2926: {
2927:   PetscMemzero(info, sizeof(MatInfo));
2928:   return 0;
2929: }

2931: /* ----------------------------------------------------------*/

2933: /*@C
2934:    MatLUFactor - Performs in-place LU factorization of matrix.

2936:    Collective on mat

2938:    Input Parameters:
2939: +  mat - the matrix
2940: .  row - row permutation
2941: .  col - column permutation
2942: -  info - options for factorization, includes
2943: $          fill - expected fill as ratio of original fill.
2944: $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2945: $                   Run with the option -info to determine an optimal value to use

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

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

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

2958:    Level: developer

2960:    Developer Note:
2961:    The Fortran interface is not autogenerated as the f90
2962:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

2964: .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2965:           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2966: @*/
2967: PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
2968: {
2969:   MatFactorInfo tinfo;

2978:   MatCheckPreallocated(mat, 1);
2979:   if (!info) {
2980:     MatFactorInfoInitialize(&tinfo);
2981:     info = &tinfo;
2982:   }

2984:   PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0);
2985:   PetscUseTypeMethod(mat, lufactor, row, col, info);
2986:   PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0);
2987:   PetscObjectStateIncrease((PetscObject)mat);
2988:   return 0;
2989: }

2991: /*@C
2992:    MatILUFactor - Performs in-place ILU factorization of matrix.

2994:    Collective on mat

2996:    Input Parameters:
2997: +  mat - the matrix
2998: .  row - row permutation
2999: .  col - column permutation
3000: -  info - structure containing
3001: $      levels - number of levels of fill.
3002: $      expected fill - as ratio of original fill.
3003: $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3004:                 missing diagonal entries)

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

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

3015:    Level: developer

3017:    Developer Note:
3018:    The Fortran interface is not autogenerated as the f90
3019:    interface definition cannot be generated correctly [due to MatFactorInfo]

3021: .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3022: @*/
3023: PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3024: {
3033:   MatCheckPreallocated(mat, 1);

3035:   PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0);
3036:   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3037:   PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0);
3038:   PetscObjectStateIncrease((PetscObject)mat);
3039:   return 0;
3040: }

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

3046:    Collective on fact

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

3058:    Notes:
3059:     See [Matrix Factorization](sec_matfactor) for additional information about factorizations

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

3065:    Level: developer

3067:    Developer Note:
3068:    The Fortran interface is not autogenerated as the f90
3069:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3071: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3072: @*/
3073: PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3074: {
3075:   MatFactorInfo tinfo;

3085:   if (!(fact)->ops->lufactorsymbolic) {
3086:     MatSolverType stype;
3087:     MatFactorGetSolverType(fact, &stype);
3088:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3089:   }
3090:   MatCheckPreallocated(mat, 2);
3091:   if (!info) {
3092:     MatFactorInfoInitialize(&tinfo);
3093:     info = &tinfo;
3094:   }

3096:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0);
3097:   (fact->ops->lufactorsymbolic)(fact, mat, row, col, info);
3098:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0);
3099:   PetscObjectStateIncrease((PetscObject)fact);
3100:   return 0;
3101: }

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

3107:    Collective on fact

3109:    Input Parameters:
3110: +  fact - the factor matrix obtained with `MatGetFactor()`
3111: .  mat - the matrix
3112: -  info - options for factorization

3114:    Notes:
3115:    See `MatLUFactor()` for in-place factorization.  See
3116:    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.

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

3122:    Level: developer

3124:     Developer Note:
3125:     The Fortran interface is not autogenerated as the f90
3126:     interface definition cannot be generated correctly [due to `MatFactorInfo`]

3128: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3129: @*/
3130: PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3131: {
3132:   MatFactorInfo tinfo;

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

3143:   MatCheckPreallocated(mat, 2);
3144:   if (!info) {
3145:     MatFactorInfoInitialize(&tinfo);
3146:     info = &tinfo;
3147:   }

3149:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0);
3150:   else PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0);
3151:   (fact->ops->lufactornumeric)(fact, mat, info);
3152:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0);
3153:   else PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0);
3154:   MatViewFromOptions(fact, NULL, "-mat_factor_view");
3155:   PetscObjectStateIncrease((PetscObject)fact);
3156:   return 0;
3157: }

3159: /*@C
3160:    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3161:    symmetric matrix.

3163:    Collective on mat

3165:    Input Parameters:
3166: +  mat - the matrix
3167: .  perm - row and column permutations
3168: -  f - expected fill as ratio of original fill

3170:    Notes:
3171:    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3172:    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.

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

3178:    Level: developer

3180:    Developer Note:
3181:    The Fortran interface is not autogenerated as the f90
3182:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3184: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3185:           `MatGetOrdering()`
3186: @*/
3187: PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3188: {
3189:   MatFactorInfo tinfo;

3198:   MatCheckPreallocated(mat, 1);
3199:   if (!info) {
3200:     MatFactorInfoInitialize(&tinfo);
3201:     info = &tinfo;
3202:   }

3204:   PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0);
3205:   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3206:   PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0);
3207:   PetscObjectStateIncrease((PetscObject)mat);
3208:   return 0;
3209: }

3211: /*@C
3212:    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3213:    of a symmetric matrix.

3215:    Collective on fact

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

3226:    Notes:
3227:    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3228:    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.

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

3234:    Level: developer

3236:    Developer Note:
3237:    The Fortran interface is not autogenerated as the f90
3238:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3240: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3241:           `MatGetOrdering()`
3242: @*/
3243: PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3244: {
3245:   MatFactorInfo tinfo;

3255:   if (!(fact)->ops->choleskyfactorsymbolic) {
3256:     MatSolverType stype;
3257:     MatFactorGetSolverType(fact, &stype);
3258:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3259:   }
3260:   MatCheckPreallocated(mat, 2);
3261:   if (!info) {
3262:     MatFactorInfoInitialize(&tinfo);
3263:     info = &tinfo;
3264:   }

3266:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3267:   (fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info);
3268:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3269:   PetscObjectStateIncrease((PetscObject)fact);
3270:   return 0;
3271: }

3273: /*@C
3274:    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3275:    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3276:    `MatCholeskyFactorSymbolic()`.

3278:    Collective on fact

3280:    Input Parameters:
3281: +  fact - the factor matrix obtained with `MatGetFactor()`
3282: .  mat - the initial matrix
3283: .  info - options for factorization
3284: -  fact - the symbolic factor of mat

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

3291:    Level: developer

3293:    Developer Note:
3294:    The Fortran interface is not autogenerated as the f90
3295:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3297: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3298: @*/
3299: PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3300: {
3301:   MatFactorInfo tinfo;

3310:              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3311:   MatCheckPreallocated(mat, 2);
3312:   if (!info) {
3313:     MatFactorInfoInitialize(&tinfo);
3314:     info = &tinfo;
3315:   }

3317:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3318:   else PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0);
3319:   (fact->ops->choleskyfactornumeric)(fact, mat, info);
3320:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3321:   else PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0);
3322:   MatViewFromOptions(fact, NULL, "-mat_factor_view");
3323:   PetscObjectStateIncrease((PetscObject)fact);
3324:   return 0;
3325: }

3327: /*@
3328:    MatQRFactor - Performs in-place QR factorization of matrix.

3330:    Collective on mat

3332:    Input Parameters:
3333: +  mat - the matrix
3334: .  col - column permutation
3335: -  info - options for factorization, includes
3336: $          fill - expected fill as ratio of original fill.
3337: $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3338: $                   Run with the option -info to determine an optimal value to use

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

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

3348:    Level: developer

3350:    Developer Note:
3351:    The Fortran interface is not autogenerated as the f90
3352:    interface definition cannot be generated correctly [due to MatFactorInfo]

3354: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3355:           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3356: @*/
3357: PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3358: {
3365:   MatCheckPreallocated(mat, 1);
3366:   PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0);
3367:   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3368:   PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0);
3369:   PetscObjectStateIncrease((PetscObject)mat);
3370:   return 0;
3371: }

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

3377:    Collective on fact

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

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

3392:    Level: developer

3394:    Developer Note:
3395:    The Fortran interface is not autogenerated as the f90
3396:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3398: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3399: @*/
3400: PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3401: {
3402:   MatFactorInfo tinfo;

3411:   MatCheckPreallocated(mat, 2);
3412:   if (!info) {
3413:     MatFactorInfoInitialize(&tinfo);
3414:     info = &tinfo;
3415:   }

3417:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0);
3418:   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3419:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0);
3420:   PetscObjectStateIncrease((PetscObject)fact);
3421:   return 0;
3422: }

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

3428:    Collective on fact

3430:    Input Parameters:
3431: +  fact - the factor matrix obtained with `MatGetFactor()`
3432: .  mat - the matrix
3433: -  info - options for factorization

3435:    Notes:
3436:    See `MatQRFactor()` for in-place factorization.

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

3442:    Level: developer

3444:    Developer Note:
3445:    The Fortran interface is not autogenerated as the f90
3446:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3448: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3449: @*/
3450: PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3451: {
3452:   MatFactorInfo tinfo;

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

3462:   MatCheckPreallocated(mat, 2);
3463:   if (!info) {
3464:     MatFactorInfoInitialize(&tinfo);
3465:     info = &tinfo;
3466:   }

3468:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0);
3469:   else PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0);
3470:   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3471:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0);
3472:   else PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0);
3473:   MatViewFromOptions(fact, NULL, "-mat_factor_view");
3474:   PetscObjectStateIncrease((PetscObject)fact);
3475:   return 0;
3476: }

3478: /* ----------------------------------------------------------------*/
3479: /*@
3480:    MatSolve - Solves A x = b, given a factored matrix.

3482:    Neighbor-wise Collective on mat

3484:    Input Parameters:
3485: +  mat - the factored matrix
3486: -  b - the right-hand-side vector

3488:    Output Parameter:
3489: .  x - the result vector

3491:    Notes:
3492:    The vectors b and x cannot be the same.  I.e., one cannot
3493:    call `MatSolve`(A,x,x).

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

3499:    Level: developer

3501: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3502: @*/
3503: PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3504: {
3515:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3516:   MatCheckPreallocated(mat, 1);

3518:   PetscLogEventBegin(MAT_Solve, mat, b, x, 0);
3519:   if (mat->factorerrortype) {
3520:     PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3521:     VecSetInf(x);
3522:   } else PetscUseTypeMethod(mat, solve, b, x);
3523:   PetscLogEventEnd(MAT_Solve, mat, b, x, 0);
3524:   PetscObjectStateIncrease((PetscObject)x);
3525:   return 0;
3526: }

3528: static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3529: {
3530:   Vec      b, x;
3531:   PetscInt N, i;
3532:   PetscErrorCode (*f)(Mat, Vec, Vec);
3533:   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;

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

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

3570:    Neighbor-wise Collective on A

3572:    Input Parameters:
3573: +  A - the factored matrix
3574: -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)

3576:    Output Parameter:
3577: .  X - the result matrix (dense matrix)

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

3583:    Level: developer

3585: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3586: @*/
3587: PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3588: {
3598:   if (!A->rmap->N && !A->cmap->N) return 0;
3600:   MatCheckPreallocated(A, 1);

3602:   PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3603:   if (!A->ops->matsolve) {
3604:     PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name);
3605:     MatMatSolve_Basic(A, B, X, PETSC_FALSE);
3606:   } else PetscUseTypeMethod(A, matsolve, B, X);
3607:   PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3608:   PetscObjectStateIncrease((PetscObject)X);
3609:   return 0;
3610: }

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

3615:    Neighbor-wise Collective on A

3617:    Input Parameters:
3618: +  A - the factored matrix
3619: -  B - the right-hand-side matrix  (`MATDENSE` matrix)

3621:    Output Parameter:
3622: .  X - the result matrix (dense matrix)

3624:    Note:
3625:    The matrices B and X cannot be the same.  I.e., one cannot
3626:    call `MatMatSolveTranspose`(A,X,X).

3628:    Level: developer

3630: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3631: @*/
3632: PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3633: {
3645:   if (!A->rmap->N && !A->cmap->N) return 0;
3647:   MatCheckPreallocated(A, 1);

3649:   PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3650:   if (!A->ops->matsolvetranspose) {
3651:     PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name);
3652:     MatMatSolve_Basic(A, B, X, PETSC_TRUE);
3653:   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3654:   PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3655:   PetscObjectStateIncrease((PetscObject)X);
3656:   return 0;
3657: }

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

3662:    Neighbor-wise Collective on A

3664:    Input Parameters:
3665: +  A - the factored matrix
3666: -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`

3668:    Output Parameter:
3669: .  X - the result matrix (dense matrix)

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

3675:    Level: developer

3677: .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3678: @*/
3679: PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3680: {

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

3696:   PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0);
3697:   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3698:   PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0);
3699:   PetscObjectStateIncrease((PetscObject)X);
3700:   return 0;
3701: }

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

3707:    Neighbor-wise Collective on mat

3709:    Input Parameters:
3710: +  mat - the factored matrix
3711: -  b - the right-hand-side vector

3713:    Output Parameter:
3714: .  x - the result vector

3716:    Notes:
3717:    `MatSolve()` should be used for most applications, as it performs
3718:    a forward solve followed by a backward solve.

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

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

3729:    Level: developer

3731: .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3732: @*/
3733: PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3734: {
3745:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3746:   MatCheckPreallocated(mat, 1);

3748:   PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0);
3749:   PetscUseTypeMethod(mat, forwardsolve, b, x);
3750:   PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0);
3751:   PetscObjectStateIncrease((PetscObject)x);
3752:   return 0;
3753: }

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

3759:    Neighbor-wise Collective on mat

3761:    Input Parameters:
3762: +  mat - the factored matrix
3763: -  b - the right-hand-side vector

3765:    Output Parameter:
3766: .  x - the result vector

3768:    Notes:
3769:    `MatSolve()` should be used for most applications, as it performs
3770:    a forward solve followed by a backward solve.

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

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

3781:    Level: developer

3783: .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3784: @*/
3785: PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3786: {
3797:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3798:   MatCheckPreallocated(mat, 1);

3800:   PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0);
3801:   PetscUseTypeMethod(mat, backwardsolve, b, x);
3802:   PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0);
3803:   PetscObjectStateIncrease((PetscObject)x);
3804:   return 0;
3805: }

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

3810:    Neighbor-wise Collective on mat

3812:    Input Parameters:
3813: +  mat - the factored matrix
3814: .  b - the right-hand-side vector
3815: -  y - the vector to be added to

3817:    Output Parameter:
3818: .  x - the result vector

3820:    Note:
3821:    The vectors b and x cannot be the same.  I.e., one cannot
3822:    call `MatSolveAdd`(A,x,y,x).

3824:    Level: developer

3826: .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3827: @*/
3828: PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3829: {
3830:   PetscScalar one = 1.0;
3831:   Vec         tmp;

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

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

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

3877:    Neighbor-wise Collective on mat

3879:    Input Parameters:
3880: +  mat - the factored matrix
3881: -  b - the right-hand-side vector

3883:    Output Parameter:
3884: .  x - the result vector

3886:    Notes:
3887:    The vectors b and x cannot be the same.  I.e., one cannot
3888:    call `MatSolveTranspose`(A,x,x).

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

3894:    Level: developer

3896: .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3897: @*/
3898: PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3899: {
3900:   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;

3911:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3912:   MatCheckPreallocated(mat, 1);
3913:   PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0);
3914:   if (mat->factorerrortype) {
3915:     PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3916:     VecSetInf(x);
3917:   } else {
3919:     (*f)(mat, b, x);
3920:   }
3921:   PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0);
3922:   PetscObjectStateIncrease((PetscObject)x);
3923:   return 0;
3924: }

3926: /*@
3927:    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3928:                       factored matrix.

3930:    Neighbor-wise Collective on mat

3932:    Input Parameters:
3933: +  mat - the factored matrix
3934: .  b - the right-hand-side vector
3935: -  y - the vector to be added to

3937:    Output Parameter:
3938: .  x - the result vector

3940:    Note:
3941:    The vectors b and x cannot be the same.  I.e., one cannot
3942:    call `MatSolveTransposeAdd`(A,x,y,x).

3944:    Level: developer

3946: .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
3947: @*/
3948: PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
3949: {
3950:   PetscScalar one = 1.0;
3951:   Vec         tmp;
3952:   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;

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

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

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

3998:    Neighbor-wise Collective on mat

4000:    Input Parameters:
4001: +  mat - the matrix
4002: .  b - the right hand side
4003: .  omega - the relaxation factor
4004: .  flag - flag indicating the type of SOR (see below)
4005: .  shift -  diagonal shift
4006: .  its - the number of iterations
4007: -  lits - the number of local iterations

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

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

4025:    Notes:
4026:    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4027:    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4028:    on each processor.

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

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

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

4039:    Vectors x and b CANNOT be the same

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

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

4049:    Level: developer

4051: .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4052: @*/
4053: PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4054: {

4070:   MatCheckPreallocated(mat, 1);
4071:   PetscLogEventBegin(MAT_SOR, mat, b, x, 0);
4072:   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4073:   PetscLogEventEnd(MAT_SOR, mat, b, x, 0);
4074:   PetscObjectStateIncrease((PetscObject)x);
4075:   return 0;
4076: }

4078: /*
4079:       Default matrix copy routine.
4080: */
4081: PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4082: {
4083:   PetscInt           i, rstart = 0, rend = 0, nz;
4084:   const PetscInt    *cwork;
4085:   const PetscScalar *vwork;

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

4103: /*@
4104:    MatCopy - Copies a matrix to another matrix.

4106:    Collective on A

4108:    Input Parameters:
4109: +  A - the matrix
4110: -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`

4112:    Output Parameter:
4113: .  B - where the copy is put

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

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

4122:    Level: intermediate

4124: .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4125: @*/
4126: PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4127: {
4128:   PetscInt i;

4135:   MatCheckPreallocated(B, 2);
4139:              A->cmap->N, B->cmap->N);
4140:   MatCheckPreallocated(A, 1);
4141:   if (A == B) return 0;

4143:   PetscLogEventBegin(MAT_Copy, A, B, 0, 0);
4144:   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4145:   else MatCopy_Basic(A, B, str);

4147:   B->stencil.dim = A->stencil.dim;
4148:   B->stencil.noc = A->stencil.noc;
4149:   for (i = 0; i <= A->stencil.dim; i++) {
4150:     B->stencil.dims[i]   = A->stencil.dims[i];
4151:     B->stencil.starts[i] = A->stencil.starts[i];
4152:   }

4154:   PetscLogEventEnd(MAT_Copy, A, B, 0, 0);
4155:   PetscObjectStateIncrease((PetscObject)B);
4156:   return 0;
4157: }

4159: /*@C
4160:    MatConvert - Converts a matrix to another matrix, either of the same
4161:    or different type.

4163:    Collective on mat

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

4173:    Output Parameter:
4174: .  M - pointer to place new matrix

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

4181:    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4182:    the MPI communicator of the generated matrix is always the same as the communicator
4183:    of the input matrix.

4185:    Level: intermediate

4187: .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4188: @*/
4189: PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4190: {
4191:   PetscBool  sametype, issame, flg;
4192:   PetscBool3 issymmetric, ishermitian;
4193:   char       convname[256], mtype[256];
4194:   Mat        B;

4201:   MatCheckPreallocated(mat, 1);

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

4206:   PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype);
4207:   PetscStrcmp(newtype, "same", &issame);

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

4216:   /* Cache Mat options because some converters use MatHeaderReplace  */
4217:   issymmetric = mat->symmetric;
4218:   ishermitian = mat->hermitian;

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

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

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

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

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

4303:     /* 5) Use a really basic converter. */
4304:     PetscInfo(mat, "Using MatConvert_Basic\n");
4305:     conv = MatConvert_Basic;

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

4329:   /* Copy Mat options */
4330:   if (issymmetric == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE);
4331:   else if (issymmetric == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE);
4332:   if (ishermitian == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE);
4333:   else if (ishermitian == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE);
4334:   return 0;
4335: }

4337: /*@C
4338:    MatFactorGetSolverType - Returns name of the package providing the factorization routines

4340:    Not Collective

4342:    Input Parameter:
4343: .  mat - the matrix, must be a factored matrix

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

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

4352:    Level: intermediate

4354: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4355: @*/
4356: PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4357: {
4358:   PetscErrorCode (*conv)(Mat, MatSolverType *);

4364:   PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv);
4365:   if (conv) (*conv)(mat, type);
4366:   else *type = MATSOLVERPETSC;
4367:   return 0;
4368: }

4370: typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4371: struct _MatSolverTypeForSpecifcType {
4372:   MatType mtype;
4373:   /* no entry for MAT_FACTOR_NONE */
4374:   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4375:   MatSolverTypeForSpecifcType next;
4376: };

4378: typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4379: struct _MatSolverTypeHolder {
4380:   char                       *name;
4381:   MatSolverTypeForSpecifcType handlers;
4382:   MatSolverTypeHolder         next;
4383: };

4385: static MatSolverTypeHolder MatSolverTypeHolders = NULL;

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

4390:    Input Parameters:
4391: +    package - name of the package, for example petsc or superlu
4392: .    mtype - the matrix type that works with this package
4393: .    ftype - the type of factorization supported by the package
4394: -    createfactor - routine that will create the factored matrix ready to be used

4396:     Level: developer

4398: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4399: @*/
4400: PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4401: {
4402:   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4403:   PetscBool                   flg;
4404:   MatSolverTypeForSpecifcType inext, iprev = NULL;

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

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

4448:    Input Parameters:
4449: +    type - name of the package, for example petsc or superlu
4450: .    ftype - the type of factorization supported by the type
4451: -    mtype - the matrix type that works with this type

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

4458:     Level: developer

4460: .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4461: @*/
4462: PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4463: {
4464:   MatSolverTypeHolder         next = MatSolverTypeHolders;
4465:   PetscBool                   flg;
4466:   MatSolverTypeForSpecifcType inext;

4468:   if (foundtype) *foundtype = PETSC_FALSE;
4469:   if (foundmtype) *foundmtype = PETSC_FALSE;
4470:   if (createfactor) *createfactor = NULL;

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

4525: PetscErrorCode MatSolverTypeDestroy(void)
4526: {
4527:   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4528:   MatSolverTypeForSpecifcType inext, iprev;

4530:   while (next) {
4531:     PetscFree(next->name);
4532:     inext = next->handlers;
4533:     while (inext) {
4534:       PetscFree(inext->mtype);
4535:       iprev = inext;
4536:       inext = inext->next;
4537:       PetscFree(iprev);
4538:     }
4539:     prev = next;
4540:     next = next->next;
4541:     PetscFree(prev);
4542:   }
4543:   MatSolverTypeHolders = NULL;
4544:   return 0;
4545: }

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

4550:    Logically Collective on mat

4552:    Input Parameters:
4553: .  mat - the matrix

4555:    Output Parameters:
4556: .  flg - `PETSC_TRUE` if uses the ordering

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

4562:    Level: developer

4564: .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4565: @*/
4566: PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4567: {
4568:   *flg = mat->canuseordering;
4569:   return 0;
4570: }

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

4575:    Logically Collective on mat

4577:    Input Parameters:
4578: .  mat - the matrix obtained with `MatGetFactor()`

4580:    Output Parameters:
4581: .  otype - the preferred type

4583:    Level: developer

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

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

4597:    Collective on mat

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

4604:    Output Parameters:
4605: .  f - the factor matrix used with MatXXFactorSymbolic() calls

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

4611:    Notes:
4612:      Users usually access the factorization solvers via `KSP`

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

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

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

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

4626:    Level: intermediate

4628: .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4629:           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4630: @*/
4631: PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4632: {
4633:   PetscBool foundtype, foundmtype;
4634:   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);


4640:   MatCheckPreallocated(mat, 1);

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

4654:   (*conv)(mat, ftype, f);
4655:   if (mat->factorprefix) MatSetOptionsPrefix(*f, mat->factorprefix);
4656:   return 0;
4657: }

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

4662:    Not Collective

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

4669:    Output Parameter:
4670: .    flg - PETSC_TRUE if the factorization is available

4672:    Notes:
4673:       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4674:      such as pastix, superlu, mumps etc.

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

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

4681:    Level: intermediate

4683: .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4684:           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4685: @*/
4686: PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4687: {
4688:   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);


4695:   MatCheckPreallocated(mat, 1);

4697:   MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv);
4698:   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4699:   return 0;
4700: }

4702: /*@
4703:    MatDuplicate - Duplicates a matrix including the non-zero structure.

4705:    Collective on mat

4707:    Input Parameters:
4708: +  mat - the matrix
4709: -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4710:         See the manual page for `MatDuplicateOption()` for an explanation of these options.

4712:    Output Parameter:
4713: .  M - pointer to place new matrix

4715:    Level: intermediate

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

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

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

4726: .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4727: @*/
4728: PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4729: {
4730:   Mat         B;
4731:   VecType     vtype;
4732:   PetscInt    i;
4733:   PetscObject dm;
4734:   void (*viewf)(void);

4741:   MatCheckPreallocated(mat, 1);

4743:   *M = NULL;
4744:   PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4745:   PetscUseTypeMethod(mat, duplicate, op, M);
4746:   PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4747:   B = *M;

4749:   MatGetOperation(mat, MATOP_VIEW, &viewf);
4750:   if (viewf) MatSetOperation(B, MATOP_VIEW, viewf);
4751:   MatGetVecType(mat, &vtype);
4752:   MatSetVecType(B, vtype);

4754:   B->stencil.dim = mat->stencil.dim;
4755:   B->stencil.noc = mat->stencil.noc;
4756:   for (i = 0; i <= mat->stencil.dim; i++) {
4757:     B->stencil.dims[i]   = mat->stencil.dims[i];
4758:     B->stencil.starts[i] = mat->stencil.starts[i];
4759:   }

4761:   B->nooffproczerorows = mat->nooffproczerorows;
4762:   B->nooffprocentries  = mat->nooffprocentries;

4764:   PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm);
4765:   if (dm) PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm);
4766:   PetscObjectStateIncrease((PetscObject)B);
4767:   return 0;
4768: }

4770: /*@
4771:    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`

4773:    Logically Collective on mat

4775:    Input Parameters:
4776: +  mat - the matrix
4777: -  v - the vector for storing the diagonal

4779:    Output Parameter:
4780: .  v - the diagonal of the matrix

4782:    Level: intermediate

4784:    Note:
4785:    Currently only correct in parallel for square matrices.

4787: .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4788: @*/
4789: PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4790: {
4795:   MatCheckPreallocated(mat, 1);

4797:   PetscUseTypeMethod(mat, getdiagonal, v);
4798:   PetscObjectStateIncrease((PetscObject)v);
4799:   return 0;
4800: }

4802: /*@C
4803:    MatGetRowMin - Gets the minimum value (of the real part) of each
4804:         row of the matrix

4806:    Logically Collective on mat

4808:    Input Parameter:
4809: .  mat - the matrix

4811:    Output Parameters:
4812: +  v - the vector for storing the maximums
4813: -  idx - the indices of the column found for each row (optional)

4815:    Level: intermediate

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

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

4823: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4824:           `MatGetRowMax()`
4825: @*/
4826: PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4827: {

4833:   if (!mat->cmap->N) {
4834:     VecSet(v, PETSC_MAX_REAL);
4835:     if (idx) {
4836:       PetscInt i, m = mat->rmap->n;
4837:       for (i = 0; i < m; i++) idx[i] = -1;
4838:     }
4839:   } else {
4840:     MatCheckPreallocated(mat, 1);
4841:   }
4842:   PetscUseTypeMethod(mat, getrowmin, v, idx);
4843:   PetscObjectStateIncrease((PetscObject)v);
4844:   return 0;
4845: }

4847: /*@C
4848:    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4849:         row of the matrix

4851:    Logically Collective on mat

4853:    Input Parameter:
4854: .  mat - the matrix

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

4860:    Level: intermediate

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

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

4868: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4869: @*/
4870: PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4871: {

4878:   if (!mat->cmap->N) {
4879:     VecSet(v, 0.0);
4880:     if (idx) {
4881:       PetscInt i, m = mat->rmap->n;
4882:       for (i = 0; i < m; i++) idx[i] = -1;
4883:     }
4884:   } else {
4885:     MatCheckPreallocated(mat, 1);
4886:     if (idx) PetscArrayzero(idx, mat->rmap->n);
4887:     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4888:   }
4889:   PetscObjectStateIncrease((PetscObject)v);
4890:   return 0;
4891: }

4893: /*@C
4894:    MatGetRowMax - Gets the maximum value (of the real part) of each
4895:         row of the matrix

4897:    Logically Collective on mat

4899:    Input Parameter:
4900: .  mat - the matrix

4902:    Output Parameters:
4903: +  v - the vector for storing the maximums
4904: -  idx - the indices of the column found for each row (optional)

4906:    Level: intermediate

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

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

4914: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4915: @*/
4916: PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
4917: {

4923:   if (!mat->cmap->N) {
4924:     VecSet(v, PETSC_MIN_REAL);
4925:     if (idx) {
4926:       PetscInt i, m = mat->rmap->n;
4927:       for (i = 0; i < m; i++) idx[i] = -1;
4928:     }
4929:   } else {
4930:     MatCheckPreallocated(mat, 1);
4931:     PetscUseTypeMethod(mat, getrowmax, v, idx);
4932:   }
4933:   PetscObjectStateIncrease((PetscObject)v);
4934:   return 0;
4935: }

4937: /*@C
4938:    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4939:         row of the matrix

4941:    Logically Collective on mat

4943:    Input Parameter:
4944: .  mat - the matrix

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

4950:    Level: intermediate

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

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

4958: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4959: @*/
4960: PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
4961: {

4967:   if (!mat->cmap->N) {
4968:     VecSet(v, 0.0);
4969:     if (idx) {
4970:       PetscInt i, m = mat->rmap->n;
4971:       for (i = 0; i < m; i++) idx[i] = -1;
4972:     }
4973:   } else {
4974:     MatCheckPreallocated(mat, 1);
4975:     if (idx) PetscArrayzero(idx, mat->rmap->n);
4976:     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
4977:   }
4978:   PetscObjectStateIncrease((PetscObject)v);
4979:   return 0;
4980: }

4982: /*@
4983:    MatGetRowSum - Gets the sum of each row of the matrix

4985:    Logically or Neighborhood Collective on mat

4987:    Input Parameters:
4988: .  mat - the matrix

4990:    Output Parameter:
4991: .  v - the vector for storing the sum of rows

4993:    Level: intermediate

4995:    Notes:
4996:     This code is slow since it is not currently specialized for different formats

4998: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
4999: @*/
5000: PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5001: {
5002:   Vec ones;

5008:   MatCheckPreallocated(mat, 1);
5009:   MatCreateVecs(mat, &ones, NULL);
5010:   VecSet(ones, 1.);
5011:   MatMult(mat, ones, v);
5012:   VecDestroy(&ones);
5013:   return 0;
5014: }

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

5020:    Collective on mat

5022:    Input Parameter:
5023: .  mat - the matrix to provide the transpose

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

5028:    Level: advanced

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

5034: .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5035: @*/
5036: PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5037: {
5038:   PetscContainer  rB = NULL;
5039:   MatParentState *rb = NULL;

5041:   PetscNew(&rb);
5042:   rb->id    = ((PetscObject)mat)->id;
5043:   rb->state = 0;
5044:   MatGetNonzeroState(mat, &rb->nonzerostate);
5045:   PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB);
5046:   PetscContainerSetPointer(rB, rb);
5047:   PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault);
5048:   PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB);
5049:   PetscObjectDereference((PetscObject)rB);
5050:   return 0;
5051: }

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

5056:    Collective on mat

5058:    Input Parameters:
5059: +  mat - the matrix to transpose
5060: -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`

5062:    Output Parameter:
5063: .  B - the transpose

5065:    Notes:
5066:      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B

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

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

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

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

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

5079:    Level: intermediate

5081: .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5082:           `MatTransposeSymbolic()`
5083: @*/
5084: PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5085: {
5086:   PetscContainer  rB = NULL;
5087:   MatParentState *rb = NULL;

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

5104:   PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0);
5105:   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5106:     PetscUseTypeMethod(mat, transpose, reuse, B);
5107:     PetscObjectStateIncrease((PetscObject)*B);
5108:   }
5109:   PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0);

5111:   if (reuse == MAT_INITIAL_MATRIX) MatTransposeSetPrecursor(mat, *B);
5112:   if (reuse != MAT_INPLACE_MATRIX) {
5113:     PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5114:     PetscContainerGetPointer(rB, (void **)&rb);
5115:     rb->state        = ((PetscObject)mat)->state;
5116:     rb->nonzerostate = mat->nonzerostate;
5117:   }
5118:   return 0;
5119: }

5121: /*@
5122:    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.

5124:    Collective on A

5126:    Input Parameters:
5127: .  A - the matrix to transpose

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

5133:    Level: intermediate

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

5138: .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5139: @*/
5140: PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5141: {
5147:   PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0);
5148:   (*A->ops->transposesymbolic)(A, B);
5149:   PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0);

5151:   MatTransposeSetPrecursor(A, *B);
5152:   return 0;
5153: }

5155: PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5156: {
5157:   PetscContainer  rB;
5158:   MatParentState *rb;

5164:   PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB);
5166:   PetscContainerGetPointer(rB, (void **)&rb);
5169:   return 0;
5170: }

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

5176:    Collective on A

5178:    Input Parameters:
5179: +  A - the matrix to test
5180: -  B - the matrix to test against, this can equal the first parameter

5182:    Output Parameters:
5183: .  flg - the result

5185:    Notes:
5186:    Only available for `MATAIJ` matrices.

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

5191:    Level: intermediate

5193: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5194: @*/
5195: PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5196: {
5197:   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);

5202:   PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f);
5203:   PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g);
5204:   *flg = PETSC_FALSE;
5205:   if (f && g) {
5207:     (*f)(A, B, tol, flg);
5208:   } else {
5209:     MatType mattype;

5211:     MatGetType(f ? B : A, &mattype);
5212:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5213:   }
5214:   return 0;
5215: }

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

5220:    Collective on mat

5222:    Input Parameters:
5223: +  mat - the matrix to transpose and complex conjugate
5224: -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`

5226:    Output Parameter:
5227: .  B - the Hermitian transpose

5229:    Level: intermediate

5231: .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5232: @*/
5233: PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5234: {
5235:   MatTranspose(mat, reuse, B);
5236: #if defined(PETSC_USE_COMPLEX)
5237:   MatConjugate(*B);
5238: #endif
5239:   return 0;
5240: }

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

5245:    Collective on A

5247:    Input Parameters:
5248: +  A - the matrix to test
5249: -  B - the matrix to test against, this can equal the first parameter

5251:    Output Parameters:
5252: .  flg - the result

5254:    Notes:
5255:    Only available for `MATAIJ` matrices.

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

5261:    Level: intermediate

5263: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5264: @*/
5265: PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5266: {
5267:   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);

5272:   PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f);
5273:   PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g);
5274:   if (f && g) {
5276:     (*f)(A, B, tol, flg);
5277:   }
5278:   return 0;
5279: }

5281: /*@
5282:    MatPermute - Creates a new matrix with rows and columns permuted from the
5283:    original.

5285:    Collective on mat

5287:    Input Parameters:
5288: +  mat - the matrix to permute
5289: .  row - row permutation, each processor supplies only the permutation for its rows
5290: -  col - column permutation, each processor supplies only the permutation for its columns

5292:    Output Parameters:
5293: .  B - the permuted matrix

5295:    Level: advanced

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

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

5306: .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5307: @*/
5308: PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5309: {
5320:   MatCheckPreallocated(mat, 1);

5322:   if (mat->ops->permute) {
5323:     PetscUseTypeMethod(mat, permute, row, col, B);
5324:     PetscObjectStateIncrease((PetscObject)*B);
5325:   } else {
5326:     MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B);
5327:   }
5328:   return 0;
5329: }

5331: /*@
5332:    MatEqual - Compares two matrices.

5334:    Collective on A

5336:    Input Parameters:
5337: +  A - the first matrix
5338: -  B - the second matrix

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

5343:    Level: intermediate

5345: .seealso: `Mat`
5346: @*/
5347: PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5348: {
5355:   MatCheckPreallocated(A, 1);
5356:   MatCheckPreallocated(B, 2);
5360:              B->cmap->N);
5361:   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5362:     PetscUseTypeMethod(A, equal, B, flg);
5363:   } else {
5364:     MatMultEqual(A, B, 10, flg);
5365:   }
5366:   return 0;
5367: }

5369: /*@
5370:    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5371:    matrices that are stored as vectors.  Either of the two scaling
5372:    matrices can be NULL.

5374:    Collective on mat

5376:    Input Parameters:
5377: +  mat - the matrix to be scaled
5378: .  l - the left scaling vector (or NULL)
5379: -  r - the right scaling vector (or NULL)

5381:    Note:
5382:    `MatDiagonalScale()` computes A = LAR, where
5383:    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5384:    The L scales the rows of the matrix, the R scales the columns of the matrix.

5386:    Level: intermediate

5388: .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5389: @*/
5390: PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5391: {
5394:   if (l) {
5397:   }
5398:   if (r) {
5401:   }
5404:   MatCheckPreallocated(mat, 1);
5405:   if (!l && !r) return 0;

5407:   PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5408:   PetscUseTypeMethod(mat, diagonalscale, l, r);
5409:   PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5410:   PetscObjectStateIncrease((PetscObject)mat);
5411:   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5412:   return 0;
5413: }

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

5418:     Logically Collective on mat

5420:     Input Parameters:
5421: +   mat - the matrix to be scaled
5422: -   a  - the scaling value

5424:     Output Parameter:
5425: .   mat - the scaled matrix

5427:     Level: intermediate

5429: .seealso: `Mat`, `MatDiagonalScale()`
5430: @*/
5431: PetscErrorCode MatScale(Mat mat, PetscScalar a)
5432: {
5439:   MatCheckPreallocated(mat, 1);

5441:   PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5442:   if (a != (PetscScalar)1.0) {
5443:     PetscUseTypeMethod(mat, scale, a);
5444:     PetscObjectStateIncrease((PetscObject)mat);
5445:   }
5446:   PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5447:   return 0;
5448: }

5450: /*@
5451:    MatNorm - Calculates various norms of a matrix.

5453:    Collective on mat

5455:    Input Parameters:
5456: +  mat - the matrix
5457: -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`

5459:    Output Parameter:
5460: .  nrm - the resulting norm

5462:    Level: intermediate

5464: .seealso: `Mat`
5465: @*/
5466: PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5467: {

5474:   MatCheckPreallocated(mat, 1);

5476:   PetscUseTypeMethod(mat, norm, type, nrm);
5477:   return 0;
5478: }

5480: /*
5481:      This variable is used to prevent counting of MatAssemblyBegin() that
5482:    are called from within a MatAssemblyEnd().
5483: */
5484: static PetscInt MatAssemblyEnd_InUse = 0;
5485: /*@
5486:    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5487:    be called after completing all calls to `MatSetValues()`.

5489:    Collective on mat

5491:    Input Parameters:
5492: +  mat - the matrix
5493: -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`

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

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

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

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

5511:    Level: beginner

5513: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5514: @*/
5515: PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5516: {
5519:   MatCheckPreallocated(mat, 1);
5521:   if (mat->assembled) {
5522:     mat->was_assembled = PETSC_TRUE;
5523:     mat->assembled     = PETSC_FALSE;
5524:   }

5526:   if (!MatAssemblyEnd_InUse) {
5527:     PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0);
5528:     PetscTryTypeMethod(mat, assemblybegin, type);
5529:     PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0);
5530:   } else PetscTryTypeMethod(mat, assemblybegin, type);
5531:   return 0;
5532: }

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

5538:    Not Collective

5540:    Input Parameter:
5541: .  mat - the matrix

5543:    Output Parameter:
5544: .  assembled - `PETSC_TRUE` or `PETSC_FALSE`

5546:    Level: advanced

5548: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5549: @*/
5550: PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5551: {
5554:   *assembled = mat->assembled;
5555:   return 0;
5556: }

5558: /*@
5559:    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5560:    be called after `MatAssemblyBegin()`.

5562:    Collective on Mat

5564:    Input Parameters:
5565: +  mat - the matrix
5566: -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`

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

5581:    Level: beginner

5583: .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5584: @*/
5585: PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5586: {
5587:   static PetscInt inassm = 0;
5588:   PetscBool       flg    = PETSC_FALSE;


5593:   inassm++;
5594:   MatAssemblyEnd_InUse++;
5595:   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5596:     PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0);
5597:     PetscTryTypeMethod(mat, assemblyend, type);
5598:     PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0);
5599:   } else PetscTryTypeMethod(mat, assemblyend, type);

5601:   /* Flush assembly is not a true assembly */
5602:   if (type != MAT_FLUSH_ASSEMBLY) {
5603:     if (mat->num_ass) {
5604:       if (!mat->symmetry_eternal) {
5605:         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5606:         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5607:       }
5608:       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5609:       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5610:     }
5611:     mat->num_ass++;
5612:     mat->assembled        = PETSC_TRUE;
5613:     mat->ass_nonzerostate = mat->nonzerostate;
5614:   }

5616:   mat->insertmode = NOT_SET_VALUES;
5617:   MatAssemblyEnd_InUse--;
5618:   PetscObjectStateIncrease((PetscObject)mat);
5619:   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5620:     MatViewFromOptions(mat, NULL, "-mat_view");

5622:     if (mat->checksymmetryonassembly) {
5623:       MatIsSymmetric(mat, mat->checksymmetrytol, &flg);
5624:       if (flg) {
5625:         PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5626:       } else {
5627:         PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5628:       }
5629:     }
5630:     if (mat->nullsp && mat->checknullspaceonassembly) MatNullSpaceTest(mat->nullsp, mat, NULL);
5631:   }
5632:   inassm--;
5633:   return 0;
5634: }

5636: /*@
5637:    MatSetOption - Sets a parameter option for a matrix. Some options
5638:    may be specific to certain storage formats.  Some options
5639:    determine how values will be inserted (or added). Sorted,
5640:    row-oriented input will generally assemble the fastest. The default
5641:    is row-oriented.

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

5645:    Input Parameters:
5646: +  mat - the matrix
5647: .  option - the option, one of those listed below (and possibly others),
5648: -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)

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

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

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

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

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

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

5687:    Some options are relevant only for particular matrix types and
5688:    are thus ignored by others.  Other options are not supported by
5689:    certain matrix types and will generate an error message if set.

5691:    If using a Fortran 77 module to compute a matrix, one may need to
5692:    use the column-oriented option (or convert to the row-oriented
5693:    format).

5695:    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5696:    that would generate a new entry in the nonzero structure is instead
5697:    ignored.  Thus, if memory has not alredy been allocated for this particular
5698:    data, then the insertion is ignored. For dense matrices, in which
5699:    the entire array is allocated, no entries are ever ignored.
5700:    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction

5702:    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5703:    that would generate a new entry in the nonzero structure instead produces
5704:    an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats only.) If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction

5706:    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5707:    that would generate a new entry that has not been preallocated will
5708:    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5709:    only.) This is a useful flag when debugging matrix memory preallocation.
5710:    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction

5712:    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5713:    other processors should be dropped, rather than stashed.
5714:    This is useful if you know that the "owning" processor is also
5715:    always generating the correct matrix entries, so that PETSc need
5716:    not transfer duplicate entries generated on another processor.

5718:    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5719:    searches during matrix assembly. When this flag is set, the hash table
5720:    is created during the first matrix assembly. This hash table is
5721:    used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5722:    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5723:    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5724:    supported by` MATMPIBAIJ` format only.

5726:    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5727:    are kept in the nonzero structure

5729:    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5730:    a zero location in the matrix

5732:    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types

5734:    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5735:         zero row routines and thus improves performance for very large process counts.

5737:    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5738:         part of the matrix (since they should match the upper triangular part).

5740:    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5741:                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5742:                      with finite difference schemes with non-periodic boundary conditions.

5744:    Developer Note:
5745:    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5746:    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5747:    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5748:    not changed.

5750:    Level: intermediate

5752: .seealso: `MatOption`, `Mat`, `MatGetOption()`
5753: @*/
5754: PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5755: {
5757:   if (op > 0) {
5760:   }


5764:   switch (op) {
5765:   case MAT_FORCE_DIAGONAL_ENTRIES:
5766:     mat->force_diagonals = flg;
5767:     return 0;
5768:   case MAT_NO_OFF_PROC_ENTRIES:
5769:     mat->nooffprocentries = flg;
5770:     return 0;
5771:   case MAT_SUBSET_OFF_PROC_ENTRIES:
5772:     mat->assembly_subset = flg;
5773:     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5774: #if !defined(PETSC_HAVE_MPIUNI)
5775:       MatStashScatterDestroy_BTS(&mat->stash);
5776: #endif
5777:       mat->stash.first_assembly_done = PETSC_FALSE;
5778:     }
5779:     return 0;
5780:   case MAT_NO_OFF_PROC_ZERO_ROWS:
5781:     mat->nooffproczerorows = flg;
5782:     return 0;
5783:   case MAT_SPD:
5784:     if (flg) {
5785:       mat->spd                    = PETSC_BOOL3_TRUE;
5786:       mat->symmetric              = PETSC_BOOL3_TRUE;
5787:       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5788:     } else {
5789:       mat->spd = PETSC_BOOL3_FALSE;
5790:     }
5791:     break;
5792:   case MAT_SYMMETRIC:
5793:     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5794:     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5795: #if !defined(PETSC_USE_COMPLEX)
5796:     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5797: #endif
5798:     break;
5799:   case MAT_HERMITIAN:
5800:     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5801:     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5802: #if !defined(PETSC_USE_COMPLEX)
5803:     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5804: #endif
5805:     break;
5806:   case MAT_STRUCTURALLY_SYMMETRIC:
5807:     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5808:     break;
5809:   case MAT_SYMMETRY_ETERNAL:
5811:     mat->symmetry_eternal = flg;
5812:     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5813:     break;
5814:   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5816:     mat->structural_symmetry_eternal = flg;
5817:     break;
5818:   case MAT_SPD_ETERNAL:
5820:     mat->spd_eternal = flg;
5821:     if (flg) {
5822:       mat->structural_symmetry_eternal = PETSC_TRUE;
5823:       mat->symmetry_eternal            = PETSC_TRUE;
5824:     }
5825:     break;
5826:   case MAT_STRUCTURE_ONLY:
5827:     mat->structure_only = flg;
5828:     break;
5829:   case MAT_SORTED_FULL:
5830:     mat->sortedfull = flg;
5831:     break;
5832:   default:
5833:     break;
5834:   }
5835:   PetscTryTypeMethod(mat, setoption, op, flg);
5836:   return 0;
5837: }

5839: /*@
5840:    MatGetOption - Gets a parameter option that has been set for a matrix.

5842:    Logically Collective on mat

5844:    Input Parameters:
5845: +  mat - the matrix
5846: -  option - the option, this only responds to certain options, check the code for which ones

5848:    Output Parameter:
5849: .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)

5851:     Notes:
5852:     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.

5854:     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5855:     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`

5857:    Level: intermediate

5859: .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5860:     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5861: @*/
5862: PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5863: {


5870:   switch (op) {
5871:   case MAT_NO_OFF_PROC_ENTRIES:
5872:     *flg = mat->nooffprocentries;
5873:     break;
5874:   case MAT_NO_OFF_PROC_ZERO_ROWS:
5875:     *flg = mat->nooffproczerorows;
5876:     break;
5877:   case MAT_SYMMETRIC:
5878:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5879:     break;
5880:   case MAT_HERMITIAN:
5881:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5882:     break;
5883:   case MAT_STRUCTURALLY_SYMMETRIC:
5884:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5885:     break;
5886:   case MAT_SPD:
5887:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
5888:     break;
5889:   case MAT_SYMMETRY_ETERNAL:
5890:     *flg = mat->symmetry_eternal;
5891:     break;
5892:   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5893:     *flg = mat->symmetry_eternal;
5894:     break;
5895:   default:
5896:     break;
5897:   }
5898:   return 0;
5899: }

5901: /*@
5902:    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5903:    this routine retains the old nonzero structure.

5905:    Logically Collective on mat

5907:    Input Parameters:
5908: .  mat - the matrix

5910:    Level: intermediate

5912:    Note:
5913:     If the matrix was not preallocated then a default, likely poor preallocation will be set in the matrix, so this should be called after the preallocation phase.
5914:    See the Performance chapter of the users manual for information on preallocating matrices.

5916: .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
5917: @*/
5918: PetscErrorCode MatZeroEntries(Mat mat)
5919: {
5924:   MatCheckPreallocated(mat, 1);

5926:   PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0);
5927:   PetscUseTypeMethod(mat, zeroentries);
5928:   PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0);
5929:   PetscObjectStateIncrease((PetscObject)mat);
5930:   return 0;
5931: }

5933: /*@
5934:    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5935:    of a set of rows and columns of a matrix.

5937:    Collective on mat

5939:    Input Parameters:
5940: +  mat - the matrix
5941: .  numRows - the number of rows to remove
5942: .  rows - the global row indices
5943: .  diag - value put in the diagonal of the eliminated rows
5944: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5945: -  b - optional vector of right hand side, that will be adjusted by provided solution

5947:    Notes:
5948:    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.

5950:    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5951:    The other entries of b will be adjusted by the known values of x times the corresponding matrix entries in the columns that are being eliminated

5953:    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5954:    Krylov method to take advantage of the known solution on the zeroed rows.

5956:    For the parallel case, all processes that share the matrix (i.e.,
5957:    those in the communicator used for matrix creation) MUST call this
5958:    routine, regardless of whether any rows being zeroed are owned by
5959:    them.

5961:    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.

5963:    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5964:    list only rows local to itself).

5966:    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.

5968:    Level: intermediate

5970: .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5971:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5972: @*/
5973: PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
5974: {
5980:   MatCheckPreallocated(mat, 1);

5982:   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
5983:   MatViewFromOptions(mat, NULL, "-mat_view");
5984:   PetscObjectStateIncrease((PetscObject)mat);
5985:   return 0;
5986: }

5988: /*@
5989:    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5990:    of a set of rows and columns of a matrix.

5992:    Collective on mat

5994:    Input Parameters:
5995: +  mat - the matrix
5996: .  is - the rows to zero
5997: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5998: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5999: -  b - optional vector of right hand side, that will be adjusted by provided solution

6001:    Note:
6002:    See `MatZeroRowsColumns()` for details on how this routine operates.

6004:    Level: intermediate

6006: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6007:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6008: @*/
6009: PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6010: {
6011:   PetscInt        numRows;
6012:   const PetscInt *rows;

6018:   ISGetLocalSize(is, &numRows);
6019:   ISGetIndices(is, &rows);
6020:   MatZeroRowsColumns(mat, numRows, rows, diag, x, b);
6021:   ISRestoreIndices(is, &rows);
6022:   return 0;
6023: }

6025: /*@
6026:    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6027:    of a set of rows of a matrix.

6029:    Collective on mat

6031:    Input Parameters:
6032: +  mat - the matrix
6033: .  numRows - the number of rows to remove
6034: .  rows - the global row indices
6035: .  diag - value put in the diagonal of the eliminated rows
6036: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6037: -  b - optional vector of right hand side, that will be adjusted by provided solution

6039:    Notes:
6040:    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.

6042:    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.

6044:    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6045:    Krylov method to take advantage of the known solution on the zeroed rows.

6047:    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reducing problem (after completely eliminating the zeroed rows and their corresponding columns)
6048:    from the matrix.

6050:    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6051:    but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal
6052:    formats this does not alter the nonzero structure.

6054:    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6055:    of the matrix is not changed the values are
6056:    merely zeroed.

6058:    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6059:    formats can optionally remove the main diagonal entry from the
6060:    nonzero structure as well, by passing 0.0 as the final argument).

6062:    For the parallel case, all processes that share the matrix (i.e.,
6063:    those in the communicator used for matrix creation) MUST call this
6064:    routine, regardless of whether any rows being zeroed are owned by
6065:    them.

6067:    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6068:    list only rows local to itself).

6070:    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6071:    owns that are to be zeroed. This saves a global synchronization in the implementation.

6073:    Level: intermediate

6075: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6076:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6077: @*/
6078: PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6079: {
6085:   MatCheckPreallocated(mat, 1);

6087:   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6088:   MatViewFromOptions(mat, NULL, "-mat_view");
6089:   PetscObjectStateIncrease((PetscObject)mat);
6090:   return 0;
6091: }

6093: /*@
6094:    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6095:    of a set of rows of a matrix.

6097:    Collective on Mat

6099:    Input Parameters:
6100: +  mat - the matrix
6101: .  is - index set of rows to remove (if NULL then no row is removed)
6102: .  diag - value put in all diagonals of eliminated rows
6103: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6104: -  b - optional vector of right hand side, that will be adjusted by provided solution

6106:    Note:
6107:    See `MatZeroRows()` for details on how this routine operates.

6109:    Level: intermediate

6111: .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6112:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6113: @*/
6114: PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6115: {
6116:   PetscInt        numRows = 0;
6117:   const PetscInt *rows    = NULL;

6121:   if (is) {
6123:     ISGetLocalSize(is, &numRows);
6124:     ISGetIndices(is, &rows);
6125:   }
6126:   MatZeroRows(mat, numRows, rows, diag, x, b);
6127:   if (is) ISRestoreIndices(is, &rows);
6128:   return 0;
6129: }

6131: /*@
6132:    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6133:    of a set of rows of a matrix. These rows must be local to the process.

6135:    Collective on mat

6137:    Input Parameters:
6138: +  mat - the matrix
6139: .  numRows - the number of rows to remove
6140: .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6141: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6142: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6143: -  b - optional vector of right hand side, that will be adjusted by provided solution

6145:    Notes:
6146:    See `MatZeroRows()` for details on how this routine operates.

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

6150:    In Fortran idxm and idxn should be declared as
6151: $     MatStencil idxm(4,m)
6152:    and the values inserted using
6153: $    idxm(MatStencil_i,1) = i
6154: $    idxm(MatStencil_j,1) = j
6155: $    idxm(MatStencil_k,1) = k
6156: $    idxm(MatStencil_c,1) = c
6157:    etc

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

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

6167:    Level: intermediate

6169: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6170:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6171: @*/
6172: PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6173: {
6174:   PetscInt  dim    = mat->stencil.dim;
6175:   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6176:   PetscInt *dims   = mat->stencil.dims + 1;
6177:   PetscInt *starts = mat->stencil.starts;
6178:   PetscInt *dxm    = (PetscInt *)rows;
6179:   PetscInt *jdxm, i, j, tmp, numNewRows = 0;


6185:   PetscMalloc1(numRows, &jdxm);
6186:   for (i = 0; i < numRows; ++i) {
6187:     /* Skip unused dimensions (they are ordered k, j, i, c) */
6188:     for (j = 0; j < 3 - sdim; ++j) dxm++;
6189:     /* Local index in X dir */
6190:     tmp = *dxm++ - starts[0];
6191:     /* Loop over remaining dimensions */
6192:     for (j = 0; j < dim - 1; ++j) {
6193:       /* If nonlocal, set index to be negative */
6194:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6195:       /* Update local index */
6196:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6197:     }
6198:     /* Skip component slot if necessary */
6199:     if (mat->stencil.noc) dxm++;
6200:     /* Local row number */
6201:     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6202:   }
6203:   MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b);
6204:   PetscFree(jdxm);
6205:   return 0;
6206: }

6208: /*@
6209:    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6210:    of a set of rows and columns of a matrix.

6212:    Collective on mat

6214:    Input Parameters:
6215: +  mat - the matrix
6216: .  numRows - the number of rows/columns to remove
6217: .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6218: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6219: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6220: -  b - optional vector of right hand side, that will be adjusted by provided solution

6222:    Notes:
6223:    See `MatZeroRowsColumns()` for details on how this routine operates.

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

6227:    In Fortran idxm and idxn should be declared as
6228: $     MatStencil idxm(4,m)
6229:    and the values inserted using
6230: $    idxm(MatStencil_i,1) = i
6231: $    idxm(MatStencil_j,1) = j
6232: $    idxm(MatStencil_k,1) = k
6233: $    idxm(MatStencil_c,1) = c
6234:    etc

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

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

6244:    Level: intermediate

6246: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6247:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6248: @*/
6249: PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6250: {
6251:   PetscInt  dim    = mat->stencil.dim;
6252:   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6253:   PetscInt *dims   = mat->stencil.dims + 1;
6254:   PetscInt *starts = mat->stencil.starts;
6255:   PetscInt *dxm    = (PetscInt *)rows;
6256:   PetscInt *jdxm, i, j, tmp, numNewRows = 0;


6262:   PetscMalloc1(numRows, &jdxm);
6263:   for (i = 0; i < numRows; ++i) {
6264:     /* Skip unused dimensions (they are ordered k, j, i, c) */
6265:     for (j = 0; j < 3 - sdim; ++j) dxm++;
6266:     /* Local index in X dir */
6267:     tmp = *dxm++ - starts[0];
6268:     /* Loop over remaining dimensions */
6269:     for (j = 0; j < dim - 1; ++j) {
6270:       /* If nonlocal, set index to be negative */
6271:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6272:       /* Update local index */
6273:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6274:     }
6275:     /* Skip component slot if necessary */
6276:     if (mat->stencil.noc) dxm++;
6277:     /* Local row number */
6278:     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6279:   }
6280:   MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b);
6281:   PetscFree(jdxm);
6282:   return 0;
6283: }

6285: /*@C
6286:    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6287:    of a set of rows of a matrix; using local numbering of rows.

6289:    Collective on mat

6291:    Input Parameters:
6292: +  mat - the matrix
6293: .  numRows - the number of rows to remove
6294: .  rows - the local row indices
6295: .  diag - value put in all diagonals of eliminated rows
6296: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6297: -  b - optional vector of right hand side, that will be adjusted by provided solution

6299:    Notes:
6300:    Before calling `MatZeroRowsLocal()`, the user must first set the
6301:    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.

6303:    See `MatZeroRows()` for details on how this routine operates.

6305:    Level: intermediate

6307: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6308:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6309: @*/
6310: PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6311: {
6317:   MatCheckPreallocated(mat, 1);

6319:   if (mat->ops->zerorowslocal) {
6320:     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6321:   } else {
6322:     IS              is, newis;
6323:     const PetscInt *newRows;

6326:     ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6327:     ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis);
6328:     ISGetIndices(newis, &newRows);
6329:     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6330:     ISRestoreIndices(newis, &newRows);
6331:     ISDestroy(&newis);
6332:     ISDestroy(&is);
6333:   }
6334:   PetscObjectStateIncrease((PetscObject)mat);
6335:   return 0;
6336: }

6338: /*@
6339:    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6340:    of a set of rows of a matrix; using local numbering of rows.

6342:    Collective on mat

6344:    Input Parameters:
6345: +  mat - the matrix
6346: .  is - index set of rows to remove
6347: .  diag - value put in all diagonals of eliminated rows
6348: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6349: -  b - optional vector of right hand side, that will be adjusted by provided solution

6351:    Notes:
6352:    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6353:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6355:    See `MatZeroRows()` for details on how this routine operates.

6357:    Level: intermediate

6359: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6360:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6361: @*/
6362: PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6363: {
6364:   PetscInt        numRows;
6365:   const PetscInt *rows;

6372:   MatCheckPreallocated(mat, 1);

6374:   ISGetLocalSize(is, &numRows);
6375:   ISGetIndices(is, &rows);
6376:   MatZeroRowsLocal(mat, numRows, rows, diag, x, b);
6377:   ISRestoreIndices(is, &rows);
6378:   return 0;
6379: }

6381: /*@
6382:    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6383:    of a set of rows and columns of a matrix; using local numbering of rows.

6385:    Collective on mat

6387:    Input Parameters:
6388: +  mat - the matrix
6389: .  numRows - the number of rows to remove
6390: .  rows - the global row indices
6391: .  diag - value put in all diagonals of eliminated rows
6392: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6393: -  b - optional vector of right hand side, that will be adjusted by provided solution

6395:    Notes:
6396:    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6397:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6399:    See `MatZeroRowsColumns()` for details on how this routine operates.

6401:    Level: intermediate

6403: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6404:           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6405: @*/
6406: PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6407: {
6408:   IS              is, newis;
6409:   const PetscInt *newRows;

6416:   MatCheckPreallocated(mat, 1);

6419:   ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6420:   ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis);
6421:   ISGetIndices(newis, &newRows);
6422:   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6423:   ISRestoreIndices(newis, &newRows);
6424:   ISDestroy(&newis);
6425:   ISDestroy(&is);
6426:   PetscObjectStateIncrease((PetscObject)mat);
6427:   return 0;
6428: }

6430: /*@
6431:    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6432:    of a set of rows and columns of a matrix; using local numbering of rows.

6434:    Collective on Mat

6436:    Input Parameters:
6437: +  mat - the matrix
6438: .  is - index set of rows to remove
6439: .  diag - value put in all diagonals of eliminated rows
6440: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6441: -  b - optional vector of right hand side, that will be adjusted by provided solution

6443:    Notes:
6444:    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6445:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6447:    See `MatZeroRowsColumns()` for details on how this routine operates.

6449:    Level: intermediate

6451: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6452:           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6453: @*/
6454: PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6455: {
6456:   PetscInt        numRows;
6457:   const PetscInt *rows;

6464:   MatCheckPreallocated(mat, 1);

6466:   ISGetLocalSize(is, &numRows);
6467:   ISGetIndices(is, &rows);
6468:   MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b);
6469:   ISRestoreIndices(is, &rows);
6470:   return 0;
6471: }

6473: /*@C
6474:    MatGetSize - Returns the numbers of rows and columns in a matrix.

6476:    Not Collective

6478:    Input Parameter:
6479: .  mat - the matrix

6481:    Output Parameters:
6482: +  m - the number of global rows
6483: -  n - the number of global columns

6485:    Note: both output parameters can be NULL on input.

6487:    Level: beginner

6489: .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6490: @*/
6491: PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6492: {
6494:   if (m) *m = mat->rmap->N;
6495:   if (n) *n = mat->cmap->N;
6496:   return 0;
6497: }

6499: /*@C
6500:    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6501:    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.

6503:    Not Collective

6505:    Input Parameter:
6506: .  mat - the matrix

6508:    Output Parameters:
6509: +  m - the number of local rows, use `NULL` to not obtain this value
6510: -  n - the number of local columns, use `NULL` to not obtain this value

6512:    Level: beginner

6514: .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6515: @*/
6516: PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6517: {
6521:   if (m) *m = mat->rmap->n;
6522:   if (n) *n = mat->cmap->n;
6523:   return 0;
6524: }

6526: /*@C
6527:    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6528:    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.

6530:    Not Collective, unless matrix has not been allocated, then collective on mat

6532:    Input Parameter:
6533: .  mat - the matrix

6535:    Output Parameters:
6536: +  m - the global index of the first local column, use `NULL` to not obtain this value
6537: -  n - one more than the global index of the last local column, use `NULL` to not obtain this value

6539:    Level: developer

6541: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6542: @*/
6543: PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6544: {
6549:   MatCheckPreallocated(mat, 1);
6550:   if (m) *m = mat->cmap->rstart;
6551:   if (n) *n = mat->cmap->rend;
6552:   return 0;
6553: }

6555: /*@C
6556:    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6557:    this MPI rank. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6558:    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts

6560:    Not Collective

6562:    Input Parameter:
6563: .  mat - the matrix

6565:    Output Parameters:
6566: +  m - the global index of the first local row, use `NULL` to not obtain this value
6567: -  n - one more than the global index of the last local row, use `NULL` to not obtain this value

6569:    Note:
6570:   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6571:   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6572:   and then `MPI_Scan()` to calculate prefix sums of the local sizes.

6574:    Level: beginner

6576: .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6577:           `PetscLayout`
6578: @*/
6579: PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6580: {
6585:   MatCheckPreallocated(mat, 1);
6586:   if (m) *m = mat->rmap->rstart;
6587:   if (n) *n = mat->rmap->rend;
6588:   return 0;
6589: }

6591: /*@C
6592:    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6593:    each process. For all matrices  it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix
6594:    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts

6596:    Not Collective, unless matrix has not been allocated, then collective on mat

6598:    Input Parameters:
6599: .  mat - the matrix

6601:    Output Parameters:
6602: .  ranges - start of each processors portion plus one more than the total length at the end

6604:    Level: beginner

6606: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6607: @*/
6608: PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6609: {
6612:   MatCheckPreallocated(mat, 1);
6613:   PetscLayoutGetRanges(mat->rmap, ranges);
6614:   return 0;
6615: }

6617: /*@C
6618:    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6619:    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.

6621:    Not Collective, unless matrix has not been allocated, then collective on Mat

6623:    Input Parameters:
6624: .  mat - the matrix

6626:    Output Parameters:
6627: .  ranges - start of each processors portion plus one more then the total length at the end

6629:    Level: beginner

6631: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6632: @*/
6633: PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6634: {
6637:   MatCheckPreallocated(mat, 1);
6638:   PetscLayoutGetRanges(mat->cmap, ranges);
6639:   return 0;
6640: }

6642: /*@C
6643:    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6644:    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6645:    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.

6647:    Not Collective

6649:    Input Parameter:
6650: .  A - matrix

6652:    Output Parameters:
6653: +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6654: -  cols - columns in which this process owns elements, use `NULL` to not obtain this value

6656:    Level: intermediate

6658: .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6659: @*/
6660: PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6661: {
6662:   PetscErrorCode (*f)(Mat, IS *, IS *);

6664:   MatCheckPreallocated(A, 1);
6665:   PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f);
6666:   if (f) {
6667:     (*f)(A, rows, cols);
6668:   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6669:     if (rows) ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows);
6670:     if (cols) ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols);
6671:   }
6672:   return 0;
6673: }

6675: /*@C
6676:    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6677:    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6678:    to complete the factorization.

6680:    Collective on fact

6682:    Input Parameters:
6683: +  fact - the factorized matrix obtained with `MatGetFactor()`
6684: .  mat - the matrix
6685: .  row - row permutation
6686: .  column - column permutation
6687: -  info - structure containing
6688: $      levels - number of levels of fill.
6689: $      expected fill - as ratio of original fill.
6690: $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6691:                 missing diagonal entries)

6693:    Output Parameters:
6694: .  fact - new matrix that has been symbolically factored

6696:    Level: developer

6698:    Notes:
6699:    See [Matrix Factorization](sec_matfactor) for additional information.

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

6705:    Uses the definition of level of fill as in Y. Saad, 2003

6707:    Developer Note:
6708:    The Fortran interface is not autogenerated as the f90
6709:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

6711:    References:
6712: .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003

6714: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6715:           `MatGetOrdering()`, `MatFactorInfo`
6716: @*/
6717: PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6718: {
6727:   if (!fact->ops->ilufactorsymbolic) {
6728:     MatSolverType stype;
6729:     MatFactorGetSolverType(fact, &stype);
6730:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6731:   }
6734:   MatCheckPreallocated(mat, 2);

6736:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0);
6737:   (fact->ops->ilufactorsymbolic)(fact, mat, row, col, info);
6738:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0);
6739:   return 0;
6740: }

6742: /*@C
6743:    MatICCFactorSymbolic - Performs symbolic incomplete
6744:    Cholesky factorization for a symmetric matrix.  Use
6745:    `MatCholeskyFactorNumeric()` to complete the factorization.

6747:    Collective on fact

6749:    Input Parameters:
6750: +  fact - the factorized matrix obtained with `MatGetFactor()`
6751: .  mat - the matrix to be factored
6752: .  perm - row and column permutation
6753: -  info - structure containing
6754: $      levels - number of levels of fill.
6755: $      expected fill - as ratio of original fill.

6757:    Output Parameter:
6758: .  fact - the factored matrix

6760:    Level: developer

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

6767:    This uses the definition of level of fill as in Y. Saad, 2003

6769:    Developer Note:
6770:    The Fortran interface is not autogenerated as the f90
6771:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

6773:    References:
6774: .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003

6776: .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6777: @*/
6778: PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6779: {
6788:   if (!(fact)->ops->iccfactorsymbolic) {
6789:     MatSolverType stype;
6790:     MatFactorGetSolverType(fact, &stype);
6791:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6792:   }
6794:   MatCheckPreallocated(mat, 2);

6796:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6797:   (fact->ops->iccfactorsymbolic)(fact, mat, perm, info);
6798:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6799:   return 0;
6800: }

6802: /*@C
6803:    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6804:    points to an array of valid matrices, they may be reused to store the new
6805:    submatrices.

6807:    Collective on mat

6809:    Input Parameters:
6810: +  mat - the matrix
6811: .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6812: .  irow, icol - index sets of rows and columns to extract
6813: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

6815:    Output Parameter:
6816: .  submat - the array of submatrices

6818:    Notes:
6819:    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6820:    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6821:    to extract a parallel submatrix.

6823:    Some matrix types place restrictions on the row and column
6824:    indices, such as that they be sorted or that they be equal to each other.

6826:    The index sets may not have duplicate entries.

6828:    When extracting submatrices from a parallel matrix, each processor can
6829:    form a different submatrix by setting the rows and columns of its
6830:    individual index sets according to the local submatrix desired.

6832:    When finished using the submatrices, the user should destroy
6833:    them with `MatDestroySubMatrices()`.

6835:    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6836:    original matrix has not changed from that last call to `MatCreateSubMatrices()`.

6838:    This routine creates the matrices in submat; you should NOT create them before
6839:    calling it. It also allocates the array of matrix pointers submat.

6841:    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6842:    request one row/column in a block, they must request all rows/columns that are in
6843:    that block. For example, if the block size is 2 you cannot request just row 0 and
6844:    column 0.

6846:    Fortran Note:
6847:    The Fortran interface is slightly different from that given below; it
6848:    requires one to pass in  as submat a `Mat` (integer) array of size at least n+1.

6850:    Level: advanced

6852: .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6853: @*/
6854: PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6855: {
6856:   PetscInt  i;
6857:   PetscBool eq;

6861:   if (n) {
6866:   }
6868:   if (n && scall == MAT_REUSE_MATRIX) {
6871:   }
6874:   MatCheckPreallocated(mat, 1);
6875:   PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6876:   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6877:   PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6878:   for (i = 0; i < n; i++) {
6879:     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6880:     ISEqualUnsorted(irow[i], icol[i], &eq);
6881:     if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6882: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
6883:     if (mat->boundtocpu && mat->bindingpropagates) {
6884:       MatBindToCPU((*submat)[i], PETSC_TRUE);
6885:       MatSetBindingPropagates((*submat)[i], PETSC_TRUE);
6886:     }
6887: #endif
6888:   }
6889:   return 0;
6890: }

6892: /*@C
6893:    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).

6895:    Collective on mat

6897:    Input Parameters:
6898: +  mat - the matrix
6899: .  n   - the number of submatrixes to be extracted
6900: .  irow, icol - index sets of rows and columns to extract
6901: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

6903:    Output Parameter:
6904: .  submat - the array of submatrices

6906:    Level: advanced

6908:    Note:
6909:    This is used by `PCGASM`

6911: .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6912: @*/
6913: PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6914: {
6915:   PetscInt  i;
6916:   PetscBool eq;

6920:   if (n) {
6925:   }
6927:   if (n && scall == MAT_REUSE_MATRIX) {
6930:   }
6933:   MatCheckPreallocated(mat, 1);

6935:   PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6936:   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6937:   PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6938:   for (i = 0; i < n; i++) {
6939:     ISEqualUnsorted(irow[i], icol[i], &eq);
6940:     if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6941:   }
6942:   return 0;
6943: }

6945: /*@C
6946:    MatDestroyMatrices - Destroys an array of matrices.

6948:    Collective on mat

6950:    Input Parameters:
6951: +  n - the number of local matrices
6952: -  mat - the matrices (note that this is a pointer to the array of matrices)

6954:    Level: advanced

6956:     Note:
6957:     Frees not only the matrices, but also the array that contains the matrices
6958:            In Fortran will not free the array.

6960: .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6961: @*/
6962: PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
6963: {
6964:   PetscInt i;

6966:   if (!*mat) return 0;

6970:   for (i = 0; i < n; i++) MatDestroy(&(*mat)[i]);

6972:   /* memory is allocated even if n = 0 */
6973:   PetscFree(*mat);
6974:   return 0;
6975: }

6977: /*@C
6978:    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.

6980:    Collective on mat

6982:    Input Parameters:
6983: +  n - the number of local matrices
6984: -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
6985:                        sequence of MatCreateSubMatrices())

6987:    Level: advanced

6989:     Note:
6990:     Frees not only the matrices, but also the array that contains the matrices
6991:            In Fortran will not free the array.

6993: .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6994: @*/
6995: PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
6996: {
6997:   Mat mat0;

6999:   if (!*mat) return 0;
7000:   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */

7004:   mat0 = (*mat)[0];
7005:   if (mat0 && mat0->ops->destroysubmatrices) {
7006:     (mat0->ops->destroysubmatrices)(n, mat);
7007:   } else {
7008:     MatDestroyMatrices(n, mat);
7009:   }
7010:   return 0;
7011: }

7013: /*@C
7014:    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process

7016:    Collective on mat

7018:    Input Parameters:
7019: .  mat - the matrix

7021:    Output Parameter:
7022: .  matstruct - the sequential matrix with the nonzero structure of mat

7024:   Level: developer

7026: .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7027: @*/
7028: PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7029: {

7035:   MatCheckPreallocated(mat, 1);

7037:   PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7038:   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7039:   PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7040:   return 0;
7041: }

7043: /*@C
7044:    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.

7046:    Collective on mat

7048:    Input Parameters:
7049: .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7050:                        sequence of `MatGetSequentialNonzeroStructure()`)

7052:    Level: advanced

7054:     Note:
7055:     Frees not only the matrices, but also the array that contains the matrices

7057: .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7058: @*/
7059: PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7060: {
7062:   MatDestroy(mat);
7063:   return 0;
7064: }

7066: /*@
7067:    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7068:    replaces the index sets by larger ones that represent submatrices with
7069:    additional overlap.

7071:    Collective on mat

7073:    Input Parameters:
7074: +  mat - the matrix
7075: .  n   - the number of index sets
7076: .  is  - the array of index sets (these index sets will changed during the call)
7077: -  ov  - the additional overlap requested

7079:    Options Database Key:
7080: .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)

7082:    Level: developer

7084:    Developer Note:
7085:    Any implementation must preserve block sizes. That is: if the row block size and the column block size of mat are equal to bs, then the output index sets must be compatible with bs.

7087: .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7088: @*/
7089: PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7090: {
7091:   PetscInt i, bs, cbs;

7097:   if (n) {
7100:   }
7103:   MatCheckPreallocated(mat, 1);

7105:   if (!ov || !n) return 0;
7106:   PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7107:   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7108:   PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7109:   MatGetBlockSizes(mat, &bs, &cbs);
7110:   if (bs == cbs) {
7111:     for (i = 0; i < n; i++) ISSetBlockSize(is[i], bs);
7112:   }
7113:   return 0;
7114: }

7116: PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);

7118: /*@
7119:    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7120:    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7121:    additional overlap.

7123:    Collective on mat

7125:    Input Parameters:
7126: +  mat - the matrix
7127: .  n   - the number of index sets
7128: .  is  - the array of index sets (these index sets will changed during the call)
7129: -  ov  - the additional overlap requested

7131: `   Options Database Key:
7132: .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)

7134:    Level: developer

7136: .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7137: @*/
7138: PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7139: {
7140:   PetscInt i;

7145:   if (n) {
7148:   }
7151:   MatCheckPreallocated(mat, 1);
7152:   if (!ov) return 0;
7153:   PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7154:   for (i = 0; i < n; i++) MatIncreaseOverlapSplit_Single(mat, &is[i], ov);
7155:   PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7156:   return 0;
7157: }

7159: /*@
7160:    MatGetBlockSize - Returns the matrix block size.

7162:    Not Collective

7164:    Input Parameter:
7165: .  mat - the matrix

7167:    Output Parameter:
7168: .  bs - block size

7170:    Notes:
7171:     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.

7173:    If the block size has not been set yet this routine returns 1.

7175:    Level: intermediate

7177: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7178: @*/
7179: PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7180: {
7183:   *bs = PetscAbs(mat->rmap->bs);
7184:   return 0;
7185: }

7187: /*@
7188:    MatGetBlockSizes - Returns the matrix block row and column sizes.

7190:    Not Collective

7192:    Input Parameter:
7193: .  mat - the matrix

7195:    Output Parameters:
7196: +  rbs - row block size
7197: -  cbs - column block size

7199:    Notes:
7200:     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7201:     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.

7203:    If a block size has not been set yet this routine returns 1.

7205:    Level: intermediate

7207: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7208: @*/
7209: PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7210: {
7214:   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7215:   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7216:   return 0;
7217: }

7219: /*@
7220:    MatSetBlockSize - Sets the matrix block size.

7222:    Logically Collective on mat

7224:    Input Parameters:
7225: +  mat - the matrix
7226: -  bs - block size

7228:    Notes:
7229:     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7230:     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.

7232:     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7233:     is compatible with the matrix local sizes.

7235:    Level: intermediate

7237: .seealso:  `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7238: @*/
7239: PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7240: {
7243:   MatSetBlockSizes(mat, bs, bs);
7244:   return 0;
7245: }

7247: typedef struct {
7248:   PetscInt         n;
7249:   IS              *is;
7250:   Mat             *mat;
7251:   PetscObjectState nonzerostate;
7252:   Mat              C;
7253: } EnvelopeData;

7255: static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7256: {
7257:   for (PetscInt i = 0; i < edata->n; i++) ISDestroy(&edata->is[i]);
7258:   PetscFree(edata->is);
7259:   PetscFree(edata);
7260:   return 0;
7261: }

7263: /*
7264:    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7265:          the sizes of these blocks in the matrix. An individual block may lie over several processes.

7267:    Collective on mat

7269:    Input Parameter:
7270: .  mat - the matrix

7272:    Notes:
7273:      There can be zeros within the blocks

7275:      The blocks can overlap between processes, including laying on more than two processes

7277: .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7278: */
7279: static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7280: {
7281:   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7282:   PetscInt          *diag, *odiag, sc;
7283:   VecScatter         scatter;
7284:   PetscScalar       *seqv;
7285:   const PetscScalar *parv;
7286:   const PetscInt    *ia, *ja;
7287:   PetscBool          set, flag, done;
7288:   Mat                AA = mat, A;
7289:   MPI_Comm           comm;
7290:   PetscMPIInt        rank, size, tag;
7291:   MPI_Status         status;
7292:   PetscContainer     container;
7293:   EnvelopeData      *edata;
7294:   Vec                seq, par;
7295:   IS                 isglobal;

7298:   MatIsSymmetricKnown(mat, &set, &flag);
7299:   if (!set || !flag) {
7300:     /* TOO: only needs nonzero structure of transpose */
7301:     MatTranspose(mat, MAT_INITIAL_MATRIX, &AA);
7302:     MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN);
7303:   }
7304:   MatAIJGetLocalMat(AA, &A);
7305:   MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);

7308:   MatGetLocalSize(mat, &n, NULL);
7309:   PetscObjectGetNewTag((PetscObject)mat, &tag);
7310:   PetscObjectGetComm((PetscObject)mat, &comm);
7311:   MPI_Comm_size(comm, &size);
7312:   MPI_Comm_rank(comm, &rank);

7314:   PetscMalloc2(n, &sizes, n, &starts);

7316:   if (rank > 0) {
7317:     MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status);
7318:     MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status);
7319:   }
7320:   MatGetOwnershipRange(mat, &rstart, NULL);
7321:   for (i = 0; i < n; i++) {
7322:     env = PetscMax(env, ja[ia[i + 1] - 1]);
7323:     II  = rstart + i;
7324:     if (env == II) {
7325:       starts[lblocks]  = tbs;
7326:       sizes[lblocks++] = 1 + II - tbs;
7327:       tbs              = 1 + II;
7328:     }
7329:   }
7330:   if (rank < size - 1) {
7331:     MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm);
7332:     MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm);
7333:   }

7335:   MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7336:   if (!set || !flag) MatDestroy(&AA);
7337:   MatDestroy(&A);

7339:   PetscNew(&edata);
7340:   MatGetNonzeroState(mat, &edata->nonzerostate);
7341:   edata->n = lblocks;
7342:   /* create IS needed for extracting blocks from the original matrix */
7343:   PetscMalloc1(lblocks, &edata->is);
7344:   for (PetscInt i = 0; i < lblocks; i++) ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]);

7346:   /* Create the resulting inverse matrix structure with preallocation information */
7347:   MatCreate(PetscObjectComm((PetscObject)mat), &edata->C);
7348:   MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
7349:   MatSetBlockSizesFromMats(edata->C, mat, mat);
7350:   MatSetType(edata->C, MATAIJ);

7352:   /* Communicate the start and end of each row, from each block to the correct rank */
7353:   /* TODO: Use PetscSF instead of VecScatter */
7354:   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7355:   VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq);
7356:   VecGetArrayWrite(seq, &seqv);
7357:   for (PetscInt i = 0; i < lblocks; i++) {
7358:     for (PetscInt j = 0; j < sizes[i]; j++) {
7359:       seqv[cnt]     = starts[i];
7360:       seqv[cnt + 1] = starts[i] + sizes[i];
7361:       cnt += 2;
7362:     }
7363:   }
7364:   VecRestoreArrayWrite(seq, &seqv);
7365:   MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
7366:   sc -= cnt;
7367:   VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par);
7368:   ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal);
7369:   VecScatterCreate(seq, NULL, par, isglobal, &scatter);
7370:   ISDestroy(&isglobal);
7371:   VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7372:   VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7373:   VecScatterDestroy(&scatter);
7374:   VecDestroy(&seq);
7375:   MatGetOwnershipRangeColumn(mat, &cstart, &cend);
7376:   PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag);
7377:   VecGetArrayRead(par, &parv);
7378:   cnt = 0;
7379:   MatGetSize(mat, NULL, &n);
7380:   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7381:     PetscInt start, end, d = 0, od = 0;

7383:     start = (PetscInt)PetscRealPart(parv[cnt]);
7384:     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7385:     cnt += 2;

7387:     if (start < cstart) {
7388:       od += cstart - start + n - cend;
7389:       d += cend - cstart;
7390:     } else if (start < cend) {
7391:       od += n - cend;
7392:       d += cend - start;
7393:     } else od += n - start;
7394:     if (end <= cstart) {
7395:       od -= cstart - end + n - cend;
7396:       d -= cend - cstart;
7397:     } else if (end < cend) {
7398:       od -= n - cend;
7399:       d -= cend - end;
7400:     } else od -= n - end;

7402:     odiag[i] = od;
7403:     diag[i]  = d;
7404:   }
7405:   VecRestoreArrayRead(par, &parv);
7406:   VecDestroy(&par);
7407:   MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL);
7408:   PetscFree2(diag, odiag);
7409:   PetscFree2(sizes, starts);

7411:   PetscContainerCreate(PETSC_COMM_SELF, &container);
7412:   PetscContainerSetPointer(container, edata);
7413:   PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy);
7414:   PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container);
7415:   PetscObjectDereference((PetscObject)container);
7416:   return 0;
7417: }

7419: /*@
7420:   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A

7422:   Collective on A

7424:   Input Parameters:
7425: . A - the matrix

7427:   Output Parameters:
7428: . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.

7430:   Note:
7431:      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.

7433:   Level: advanced

7435: .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7436: @*/
7437: PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7438: {
7439:   PetscContainer   container;
7440:   EnvelopeData    *edata;
7441:   PetscObjectState nonzerostate;

7443:   PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7444:   if (!container) {
7445:     MatComputeVariableBlockEnvelope(A);
7446:     PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7447:   }
7448:   PetscContainerGetPointer(container, (void **)&edata);
7449:   MatGetNonzeroState(A, &nonzerostate);

7453:   MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat);
7454:   *C = edata->C;

7456:   for (PetscInt i = 0; i < edata->n; i++) {
7457:     Mat          D;
7458:     PetscScalar *dvalues;

7460:     MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D);
7461:     MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE);
7462:     MatSeqDenseInvert(D);
7463:     MatDenseGetArray(D, &dvalues);
7464:     MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES);
7465:     MatDestroy(&D);
7466:   }
7467:   MatDestroySubMatrices(edata->n, &edata->mat);
7468:   MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY);
7469:   MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY);
7470:   return 0;
7471: }

7473: /*@
7474:    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size

7476:    Logically Collective on mat

7478:    Input Parameters:
7479: +  mat - the matrix
7480: .  nblocks - the number of blocks on this process, each block can only exist on a single process
7481: -  bsizes - the block sizes

7483:    Notes:
7484:     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices

7486:     Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks.

7488:    Level: intermediate

7490: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7491:           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7492: @*/
7493: PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7494: {
7495:   PetscInt i, ncnt = 0, nlocal;

7499:   MatGetLocalSize(mat, &nlocal, NULL);
7500:   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7502:   PetscFree(mat->bsizes);
7503:   mat->nblocks = nblocks;
7504:   PetscMalloc1(nblocks, &mat->bsizes);
7505:   PetscArraycpy(mat->bsizes, bsizes, nblocks);
7506:   return 0;
7507: }

7509: /*@C
7510:    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size

7512:    Logically Collective on mat

7514:    Input Parameter:
7515: .  mat - the matrix

7517:    Output Parameters:
7518: +  nblocks - the number of blocks on this process
7519: -  bsizes - the block sizes

7521:    Fortran Note:
7522:    Currently not supported from Fortran

7524:    Level: intermediate

7526: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7527: @*/
7528: PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7529: {
7531:   *nblocks = mat->nblocks;
7532:   *bsizes  = mat->bsizes;
7533:   return 0;
7534: }

7536: /*@
7537:    MatSetBlockSizes - Sets the matrix block row and column sizes.

7539:    Logically Collective on mat

7541:    Input Parameters:
7542: +  mat - the matrix
7543: .  rbs - row block size
7544: -  cbs - column block size

7546:    Notes:
7547:     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7548:     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7549:     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.

7551:     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7552:     are compatible with the matrix local sizes.

7554:     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.

7556:    Level: intermediate

7558: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7559: @*/
7560: PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7561: {
7565:   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7566:   if (mat->rmap->refcnt) {
7567:     ISLocalToGlobalMapping l2g  = NULL;
7568:     PetscLayout            nmap = NULL;

7570:     PetscLayoutDuplicate(mat->rmap, &nmap);
7571:     if (mat->rmap->mapping) ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g);
7572:     PetscLayoutDestroy(&mat->rmap);
7573:     mat->rmap          = nmap;
7574:     mat->rmap->mapping = l2g;
7575:   }
7576:   if (mat->cmap->refcnt) {
7577:     ISLocalToGlobalMapping l2g  = NULL;
7578:     PetscLayout            nmap = NULL;

7580:     PetscLayoutDuplicate(mat->cmap, &nmap);
7581:     if (mat->cmap->mapping) ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g);
7582:     PetscLayoutDestroy(&mat->cmap);
7583:     mat->cmap          = nmap;
7584:     mat->cmap->mapping = l2g;
7585:   }
7586:   PetscLayoutSetBlockSize(mat->rmap, rbs);
7587:   PetscLayoutSetBlockSize(mat->cmap, cbs);
7588:   return 0;
7589: }

7591: /*@
7592:    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices

7594:    Logically Collective on mat

7596:    Input Parameters:
7597: +  mat - the matrix
7598: .  fromRow - matrix from which to copy row block size
7599: -  fromCol - matrix from which to copy column block size (can be same as fromRow)

7601:    Level: developer

7603: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7604: @*/
7605: PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7606: {
7610:   if (fromRow->rmap->bs > 0) PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs);
7611:   if (fromCol->cmap->bs > 0) PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs);
7612:   return 0;
7613: }

7615: /*@
7616:    MatResidual - Default routine to calculate the residual r = b - Ax

7618:    Collective on mat

7620:    Input Parameters:
7621: +  mat - the matrix
7622: .  b   - the right-hand-side
7623: -  x   - the approximate solution

7625:    Output Parameter:
7626: .  r - location to store the residual

7628:    Level: developer

7630: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7631: @*/
7632: PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7633: {
7639:   MatCheckPreallocated(mat, 1);
7640:   PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0);
7641:   if (!mat->ops->residual) {
7642:     MatMult(mat, x, r);
7643:     VecAYPX(r, -1.0, b);
7644:   } else {
7645:     PetscUseTypeMethod(mat, residual, b, x, r);
7646:   }
7647:   PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0);
7648:   return 0;
7649: }

7651: /*@C
7652:     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix

7654:    Collective on mat

7656:     Input Parameters:
7657: +   mat - the matrix
7658: .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7659: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7660: -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7661:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7662:                  always used.

7664:     Output Parameters:
7665: +   n - number of local rows in the (possibly compressed) matrix, use NULL if not needed
7666: .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix, use NULL if not needed
7667: .   ja - the column indices, use NULL if not needed
7668: -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7669:            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set

7671:     Level: developer

7673:     Notes:
7674:     You CANNOT change any of the ia[] or ja[] values.

7676:     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.

7678:     Fortran Notes:
7679:     In Fortran use
7680: $
7681: $      PetscInt ia(1), ja(1)
7682: $      PetscOffset iia, jja
7683: $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7684: $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)

7686:      or
7687: $
7688: $    PetscInt, pointer :: ia(:),ja(:)
7689: $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7690: $    ! Access the ith and jth entries via ia(i) and ja(j)

7692: .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7693: @*/
7694: PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7695: {
7702:   MatCheckPreallocated(mat, 1);
7703:   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7704:   else {
7705:     if (done) *done = PETSC_TRUE;
7706:     PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0);
7707:     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7708:     PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0);
7709:   }
7710:   return 0;
7711: }

7713: /*@C
7714:     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.

7716:     Collective on mat

7718:     Input Parameters:
7719: +   mat - the matrix
7720: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7721: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7722:                 symmetrized
7723: .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7724:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7725:                  always used.
7726: .   n - number of columns in the (possibly compressed) matrix
7727: .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7728: -   ja - the row indices

7730:     Output Parameters:
7731: .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned

7733:     Level: developer

7735: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7736: @*/
7737: PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7738: {
7745:   MatCheckPreallocated(mat, 1);
7746:   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7747:   else {
7748:     *done = PETSC_TRUE;
7749:     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7750:   }
7751:   return 0;
7752: }

7754: /*@C
7755:     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.

7757:     Collective on mat

7759:     Input Parameters:
7760: +   mat - the matrix
7761: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7762: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7763: .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7764:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7765:                  always used.
7766: .   n - size of (possibly compressed) matrix
7767: .   ia - the row pointers
7768: -   ja - the column indices

7770:     Output Parameters:
7771: .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned

7773:     Note:
7774:     This routine zeros out n, ia, and ja. This is to prevent accidental
7775:     us of the array after it has been restored. If you pass NULL, it will
7776:     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.

7778:     Level: developer

7780: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7781: @*/
7782: PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7783: {
7789:   MatCheckPreallocated(mat, 1);

7791:   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7792:   else {
7793:     if (done) *done = PETSC_TRUE;
7794:     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7795:     if (n) *n = 0;
7796:     if (ia) *ia = NULL;
7797:     if (ja) *ja = NULL;
7798:   }
7799:   return 0;
7800: }

7802: /*@C
7803:     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.

7805:     Collective on Mat

7807:     Input Parameters:
7808: +   mat - the matrix
7809: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7810: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7811: -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7812:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7813:                  always used.

7815:     Output Parameters:
7816: +   n - size of (possibly compressed) matrix
7817: .   ia - the column pointers
7818: .   ja - the row indices
7819: -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned

7821:     Level: developer

7823: .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7824: @*/
7825: PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7826: {
7832:   MatCheckPreallocated(mat, 1);

7834:   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7835:   else {
7836:     *done = PETSC_TRUE;
7837:     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7838:     if (n) *n = 0;
7839:     if (ia) *ia = NULL;
7840:     if (ja) *ja = NULL;
7841:   }
7842:   return 0;
7843: }

7845: /*@C
7846:     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.

7848:     Collective on mat

7850:     Input Parameters:
7851: +   mat - the matrix
7852: .   ncolors - max color value
7853: .   n   - number of entries in colorarray
7854: -   colorarray - array indicating color for each column

7856:     Output Parameters:
7857: .   iscoloring - coloring generated using colorarray information

7859:     Level: developer

7861: .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7862: @*/
7863: PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
7864: {
7869:   MatCheckPreallocated(mat, 1);

7871:   if (!mat->ops->coloringpatch) {
7872:     ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring);
7873:   } else {
7874:     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7875:   }
7876:   return 0;
7877: }

7879: /*@
7880:    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.

7882:    Logically Collective on mat

7884:    Input Parameter:
7885: .  mat - the factored matrix to be reset

7887:    Notes:
7888:    This routine should be used only with factored matrices formed by in-place
7889:    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
7890:    format).  This option can save memory, for example, when solving nonlinear
7891:    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7892:    ILU(0) preconditioner.

7894:    Note that one can specify in-place ILU(0) factorization by calling
7895: .vb
7896:      PCType(pc,PCILU);
7897:      PCFactorSeUseInPlace(pc);
7898: .ve
7899:    or by using the options -pc_type ilu -pc_factor_in_place

7901:    In-place factorization ILU(0) can also be used as a local
7902:    solver for the blocks within the block Jacobi or additive Schwarz
7903:    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
7904:    for details on setting local solver options.

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

7910:    Level: developer

7912: .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7913: @*/
7914: PetscErrorCode MatSetUnfactored(Mat mat)
7915: {
7918:   MatCheckPreallocated(mat, 1);
7919:   mat->factortype = MAT_FACTOR_NONE;
7920:   if (!mat->ops->setunfactored) return 0;
7921:   PetscUseTypeMethod(mat, setunfactored);
7922:   return 0;
7923: }

7925: /*MC
7926:     MatDenseGetArrayF90 - Accesses a matrix array from Fortran

7928:     Synopsis:
7929:     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)

7931:     Not collective

7933:     Input Parameter:
7934: .   x - matrix

7936:     Output Parameters:
7937: +   xx_v - the Fortran pointer to the array
7938: -   ierr - error code

7940:     Example of Usage:
7941: .vb
7942:       PetscScalar, pointer xx_v(:,:)
7943:       ....
7944:       call MatDenseGetArrayF90(x,xx_v,ierr)
7945:       a = xx_v(3)
7946:       call MatDenseRestoreArrayF90(x,xx_v,ierr)
7947: .ve

7949:     Level: advanced

7951: .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`

7953: M*/

7955: /*MC
7956:     MatDenseRestoreArrayF90 - Restores a matrix array that has been
7957:     accessed with `MatDenseGetArrayF90()`.

7959:     Synopsis:
7960:     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)

7962:     Not collective

7964:     Input Parameters:
7965: +   x - matrix
7966: -   xx_v - the Fortran90 pointer to the array

7968:     Output Parameter:
7969: .   ierr - error code

7971:     Example of Usage:
7972: .vb
7973:        PetscScalar, pointer xx_v(:,:)
7974:        ....
7975:        call MatDenseGetArrayF90(x,xx_v,ierr)
7976:        a = xx_v(3)
7977:        call MatDenseRestoreArrayF90(x,xx_v,ierr)
7978: .ve

7980:     Level: advanced

7982: .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`

7984: M*/

7986: /*MC
7987:     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.

7989:     Synopsis:
7990:     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)

7992:     Not collective

7994:     Input Parameter:
7995: .   x - matrix

7997:     Output Parameters:
7998: +   xx_v - the Fortran pointer to the array
7999: -   ierr - error code

8001:     Example of Usage:
8002: .vb
8003:       PetscScalar, pointer xx_v(:)
8004:       ....
8005:       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8006:       a = xx_v(3)
8007:       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8008: .ve

8010:     Level: advanced

8012: .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`

8014: M*/

8016: /*MC
8017:     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8018:     accessed with `MatSeqAIJGetArrayF90()`.

8020:     Synopsis:
8021:     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)

8023:     Not collective

8025:     Input Parameters:
8026: +   x - matrix
8027: -   xx_v - the Fortran90 pointer to the array

8029:     Output Parameter:
8030: .   ierr - error code

8032:     Example of Usage:
8033: .vb
8034:        PetscScalar, pointer xx_v(:)
8035:        ....
8036:        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8037:        a = xx_v(3)
8038:        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8039: .ve

8041:     Level: advanced

8043: .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`

8045: M*/

8047: /*@
8048:     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8049:                       as the original matrix.

8051:     Collective on mat

8053:     Input Parameters:
8054: +   mat - the original matrix
8055: .   isrow - parallel IS containing the rows this processor should obtain
8056: .   iscol - parallel IS containing all columns you wish to keep. Each process should list the columns that will be in IT's "diagonal part" in the new matrix.
8057: -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

8059:     Output Parameter:
8060: .   newmat - the new submatrix, of the same type as the old

8062:     Level: advanced

8064:     Notes:
8065:     The submatrix will be able to be multiplied with vectors using the same layout as iscol.

8067:     Some matrix types place restrictions on the row and column indices, such
8068:     as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block;
8069:     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.

8071:     The index sets may not have duplicate entries.

8073:       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8074:    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8075:    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8076:    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8077:    you are finished using it.

8079:     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8080:     the input matrix.

8082:     If iscol is NULL then all columns are obtained (not supported in Fortran).

8084:    Example usage:
8085:    Consider the following 8x8 matrix with 34 non-zero values, that is
8086:    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8087:    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8088:    as follows:

8090: .vb
8091:             1  2  0  |  0  3  0  |  0  4
8092:     Proc0   0  5  6  |  7  0  0  |  8  0
8093:             9  0 10  | 11  0  0  | 12  0
8094:     -------------------------------------
8095:            13  0 14  | 15 16 17  |  0  0
8096:     Proc1   0 18  0  | 19 20 21  |  0  0
8097:             0  0  0  | 22 23  0  | 24  0
8098:     -------------------------------------
8099:     Proc2  25 26 27  |  0  0 28  | 29  0
8100:            30  0  0  | 31 32 33  |  0 34
8101: .ve

8103:     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is

8105: .vb
8106:             2  0  |  0  3  0  |  0
8107:     Proc0   5  6  |  7  0  0  |  8
8108:     -------------------------------
8109:     Proc1  18  0  | 19 20 21  |  0
8110:     -------------------------------
8111:     Proc2  26 27  |  0  0 28  | 29
8112:             0  0  | 31 32 33  |  0
8113: .ve

8115: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8116: @*/
8117: PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8118: {
8119:   PetscMPIInt size;
8120:   Mat        *local;
8121:   IS          iscoltmp;
8122:   PetscBool   flg;


8133:   MatCheckPreallocated(mat, 1);
8134:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);

8136:   if (!iscol || isrow == iscol) {
8137:     PetscBool   stride;
8138:     PetscMPIInt grabentirematrix = 0, grab;
8139:     PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride);
8140:     if (stride) {
8141:       PetscInt first, step, n, rstart, rend;
8142:       ISStrideGetInfo(isrow, &first, &step);
8143:       if (step == 1) {
8144:         MatGetOwnershipRange(mat, &rstart, &rend);
8145:         if (rstart == first) {
8146:           ISGetLocalSize(isrow, &n);
8147:           if (n == rend - rstart) grabentirematrix = 1;
8148:         }
8149:       }
8150:     }
8151:     MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat));
8152:     if (grab) {
8153:       PetscInfo(mat, "Getting entire matrix as submatrix\n");
8154:       if (cll == MAT_INITIAL_MATRIX) {
8155:         *newmat = mat;
8156:         PetscObjectReference((PetscObject)mat);
8157:       }
8158:       return 0;
8159:     }
8160:   }

8162:   if (!iscol) {
8163:     ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp);
8164:   } else {
8165:     iscoltmp = iscol;
8166:   }

8168:   /* if original matrix is on just one processor then use submatrix generated */
8169:   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8170:     MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat);
8171:     goto setproperties;
8172:   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8173:     MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local);
8174:     *newmat = *local;
8175:     PetscFree(local);
8176:     goto setproperties;
8177:   } else if (!mat->ops->createsubmatrix) {
8178:     /* Create a new matrix type that implements the operation using the full matrix */
8179:     PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8180:     switch (cll) {
8181:     case MAT_INITIAL_MATRIX:
8182:       MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat);
8183:       break;
8184:     case MAT_REUSE_MATRIX:
8185:       MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp);
8186:       break;
8187:     default:
8188:       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8189:     }
8190:     PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8191:     goto setproperties;
8192:   }

8194:   PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8195:   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8196:   PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);

8198: setproperties:
8199:   ISEqualUnsorted(isrow, iscoltmp, &flg);
8200:   if (flg) MatPropagateSymmetryOptions(mat, *newmat);
8201:   if (!iscol) ISDestroy(&iscoltmp);
8202:   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscObjectStateIncrease((PetscObject)*newmat);
8203:   return 0;
8204: }

8206: /*@
8207:    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix

8209:    Not Collective

8211:    Input Parameters:
8212: +  A - the matrix we wish to propagate options from
8213: -  B - the matrix we wish to propagate options to

8215:    Level: beginner

8217:    Note:
8218:    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`

8220: .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8221: @*/
8222: PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8223: {
8226:   B->symmetry_eternal            = A->symmetry_eternal;
8227:   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8228:   B->symmetric                   = A->symmetric;
8229:   B->structurally_symmetric      = A->structurally_symmetric;
8230:   B->spd                         = A->spd;
8231:   B->hermitian                   = A->hermitian;
8232:   return 0;
8233: }

8235: /*@
8236:    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8237:    used during the assembly process to store values that belong to
8238:    other processors.

8240:    Not Collective

8242:    Input Parameters:
8243: +  mat   - the matrix
8244: .  size  - the initial size of the stash.
8245: -  bsize - the initial size of the block-stash(if used).

8247:    Options Database Keys:
8248: +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8249: -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>

8251:    Level: intermediate

8253:    Notes:
8254:      The block-stash is used for values set with `MatSetValuesBlocked()` while
8255:      the stash is used for values set with `MatSetValues()`

8257:      Run with the option -info and look for output of the form
8258:      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8259:      to determine the appropriate value, MM, to use for size and
8260:      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8261:      to determine the value, BMM to use for bsize

8263: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8264: @*/
8265: PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8266: {
8269:   MatStashSetInitialSize_Private(&mat->stash, size);
8270:   MatStashSetInitialSize_Private(&mat->bstash, bsize);
8271:   return 0;
8272: }

8274: /*@
8275:    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8276:      the matrix

8278:    Neighbor-wise Collective on mat

8280:    Input Parameters:
8281: +  mat   - the matrix
8282: .  x,y - the vectors
8283: -  w - where the result is stored

8285:    Level: intermediate

8287:    Notes:
8288:     w may be the same vector as y.

8290:     This allows one to use either the restriction or interpolation (its transpose)
8291:     matrix to do the interpolation

8293: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8294: @*/
8295: PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8296: {
8297:   PetscInt M, N, Ny;

8303:   MatGetSize(A, &M, &N);
8304:   VecGetSize(y, &Ny);
8305:   if (M == Ny) {
8306:     MatMultAdd(A, x, y, w);
8307:   } else {
8308:     MatMultTransposeAdd(A, x, y, w);
8309:   }
8310:   return 0;
8311: }

8313: /*@
8314:    MatInterpolate - y = A*x or A'*x depending on the shape of
8315:      the matrix

8317:    Neighbor-wise Collective on mat

8319:    Input Parameters:
8320: +  mat   - the matrix
8321: -  x,y - the vectors

8323:    Level: intermediate

8325:    Note:
8326:     This allows one to use either the restriction or interpolation (its transpose)
8327:     matrix to do the interpolation

8329: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8330: @*/
8331: PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8332: {
8333:   PetscInt M, N, Ny;

8338:   MatGetSize(A, &M, &N);
8339:   VecGetSize(y, &Ny);
8340:   if (M == Ny) {
8341:     MatMult(A, x, y);
8342:   } else {
8343:     MatMultTranspose(A, x, y);
8344:   }
8345:   return 0;
8346: }

8348: /*@
8349:    MatRestrict - y = A*x or A'*x

8351:    Neighbor-wise Collective on Mat

8353:    Input Parameters:
8354: +  mat   - the matrix
8355: -  x,y - the vectors

8357:    Level: intermediate

8359:    Note:
8360:     This allows one to use either the restriction or interpolation (its transpose)
8361:     matrix to do the restriction

8363: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8364: @*/
8365: PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8366: {
8367:   PetscInt M, N, Ny;

8372:   MatGetSize(A, &M, &N);
8373:   VecGetSize(y, &Ny);
8374:   if (M == Ny) {
8375:     MatMult(A, x, y);
8376:   } else {
8377:     MatMultTranspose(A, x, y);
8378:   }
8379:   return 0;
8380: }

8382: /*@
8383:    MatMatInterpolateAdd - Y = W + A*X or W + A'*X

8385:    Neighbor-wise Collective on Mat

8387:    Input Parameters:
8388: +  mat   - the matrix
8389: -  w, x - the input dense matrices

8391:    Output Parameters:
8392: .  y - the output dense matrix

8394:    Level: intermediate

8396:    Note:
8397:     This allows one to use either the restriction or interpolation (its transpose)
8398:     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8399:     otherwise it will be recreated. y must be initialized to NULL if not supplied.

8401: .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8402: @*/
8403: PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8404: {
8405:   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8406:   PetscBool trans = PETSC_TRUE;
8407:   MatReuse  reuse = MAT_INITIAL_MATRIX;

8414:   MatGetSize(A, &M, &N);
8415:   MatGetSize(x, &Mx, &Nx);
8416:   if (N == Mx) trans = PETSC_FALSE;
8418:   Mo = trans ? N : M;
8419:   if (*y) {
8420:     MatGetSize(*y, &My, &Ny);
8421:     if (Mo == My && Nx == Ny) {
8422:       reuse = MAT_REUSE_MATRIX;
8423:     } else {
8425:       MatDestroy(y);
8426:     }
8427:   }

8429:   if (w && *y == w) { /* this is to minimize changes in PCMG */
8430:     PetscBool flg;

8432:     PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w);
8433:     if (w) {
8434:       PetscInt My, Ny, Mw, Nw;

8436:       PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg);
8437:       MatGetSize(*y, &My, &Ny);
8438:       MatGetSize(w, &Mw, &Nw);
8439:       if (!flg || My != Mw || Ny != Nw) w = NULL;
8440:     }
8441:     if (!w) {
8442:       MatDuplicate(*y, MAT_COPY_VALUES, &w);
8443:       PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w);
8444:       PetscObjectDereference((PetscObject)w);
8445:     } else {
8446:       MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN);
8447:     }
8448:   }
8449:   if (!trans) {
8450:     MatMatMult(A, x, reuse, PETSC_DEFAULT, y);
8451:   } else {
8452:     MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y);
8453:   }
8454:   if (w) MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN);
8455:   return 0;
8456: }

8458: /*@
8459:    MatMatInterpolate - Y = A*X or A'*X

8461:    Neighbor-wise Collective on Mat

8463:    Input Parameters:
8464: +  mat   - the matrix
8465: -  x - the input dense matrix

8467:    Output Parameters:
8468: .  y - the output dense matrix

8470:    Level: intermediate

8472:    Note:
8473:     This allows one to use either the restriction or interpolation (its transpose)
8474:     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8475:     otherwise it will be recreated. y must be initialized to NULL if not supplied.

8477: .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8478: @*/
8479: PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8480: {
8481:   MatMatInterpolateAdd(A, x, NULL, y);
8482:   return 0;
8483: }

8485: /*@
8486:    MatMatRestrict - Y = A*X or A'*X

8488:    Neighbor-wise Collective on Mat

8490:    Input Parameters:
8491: +  mat   - the matrix
8492: -  x - the input dense matrix

8494:    Output Parameters:
8495: .  y - the output dense matrix

8497:    Level: intermediate

8499:    Note:
8500:     This allows one to use either the restriction or interpolation (its transpose)
8501:     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8502:     otherwise it will be recreated. y must be initialized to NULL if not supplied.

8504: .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8505: @*/
8506: PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8507: {
8508:   MatMatInterpolateAdd(A, x, NULL, y);
8509:   return 0;
8510: }

8512: /*@
8513:    MatGetNullSpace - retrieves the null space of a matrix.

8515:    Logically Collective on mat

8517:    Input Parameters:
8518: +  mat - the matrix
8519: -  nullsp - the null space object

8521:    Level: developer

8523: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8524: @*/
8525: PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8526: {
8529:   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8530:   return 0;
8531: }

8533: /*@
8534:    MatSetNullSpace - attaches a null space to a matrix.

8536:    Logically Collective on mat

8538:    Input Parameters:
8539: +  mat - the matrix
8540: -  nullsp - the null space object

8542:    Level: advanced

8544:    Notes:
8545:       This null space is used by the `KSP` linear solvers to solve singular systems.

8547:       Overwrites any previous null space that may have been attached. You can remove the null space from the matrix object by calling this routine with an nullsp of NULL

8549:       For inconsistent singular systems (linear systems where the right hand side is not in the range of the operator) the `KSP` residuals will not converge to
8550:       to zero but the linear system will still be solved in a least squares sense.

8552:       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8553:    the domain of a matrix A (from R^n to R^m (m rows, n columns) R^n = the direct sum of the null space of A, n(A), + the range of A^T, R(A^T).
8554:    Similarly R^m = direct sum n(A^T) + R(A).  Hence the linear system A x = b has a solution only if b in R(A) (or correspondingly b is orthogonal to
8555:    n(A^T)) and if x is a solution then x + alpha n(A) is a solution for any alpha. The minimum norm solution is orthogonal to n(A). For problems without a solution
8556:    the solution that minimizes the norm of the residual (the least squares solution) can be obtained by solving A x = \hat{b} where \hat{b} is b orthogonalized to the n(A^T).
8557:    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.

8559:     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8560:     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8561:     routine also automatically calls `MatSetTransposeNullSpace()`.

8563:     The user should call `MatNullSpaceDestroy()`.

8565: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8566:           `KSPSetPCSide()`
8567: @*/
8568: PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8569: {
8572:   if (nullsp) PetscObjectReference((PetscObject)nullsp);
8573:   MatNullSpaceDestroy(&mat->nullsp);
8574:   mat->nullsp = nullsp;
8575:   if (mat->symmetric == PETSC_BOOL3_TRUE) MatSetTransposeNullSpace(mat, nullsp);
8576:   return 0;
8577: }

8579: /*@
8580:    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.

8582:    Logically Collective on mat

8584:    Input Parameters:
8585: +  mat - the matrix
8586: -  nullsp - the null space object

8588:    Level: developer

8590: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8591: @*/
8592: PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8593: {
8597:   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8598:   return 0;
8599: }

8601: /*@
8602:    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix

8604:    Logically Collective on mat

8606:    Input Parameters:
8607: +  mat - the matrix
8608: -  nullsp - the null space object

8610:    Level: advanced

8612:    Notes:
8613:    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.

8615:    See `MatSetNullSpace()`

8617: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8618: @*/
8619: PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8620: {
8623:   if (nullsp) PetscObjectReference((PetscObject)nullsp);
8624:   MatNullSpaceDestroy(&mat->transnullsp);
8625:   mat->transnullsp = nullsp;
8626:   return 0;
8627: }

8629: /*@
8630:    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8631:         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.

8633:    Logically Collective on mat

8635:    Input Parameters:
8636: +  mat - the matrix
8637: -  nullsp - the null space object

8639:    Level: advanced

8641:    Notes:
8642:    Overwrites any previous near null space that may have been attached

8644:    You can remove the null space by calling this routine with an nullsp of NULL

8646: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8647: @*/
8648: PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8649: {
8653:   MatCheckPreallocated(mat, 1);
8654:   if (nullsp) PetscObjectReference((PetscObject)nullsp);
8655:   MatNullSpaceDestroy(&mat->nearnullsp);
8656:   mat->nearnullsp = nullsp;
8657:   return 0;
8658: }

8660: /*@
8661:    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`

8663:    Not Collective

8665:    Input Parameter:
8666: .  mat - the matrix

8668:    Output Parameter:
8669: .  nullsp - the null space object, NULL if not set

8671:    Level: advanced

8673: .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8674: @*/
8675: PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8676: {
8680:   MatCheckPreallocated(mat, 1);
8681:   *nullsp = mat->nearnullsp;
8682:   return 0;
8683: }

8685: /*@C
8686:    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.

8688:    Collective on mat

8690:    Input Parameters:
8691: +  mat - the matrix
8692: .  row - row/column permutation
8693: .  fill - expected fill factor >= 1.0
8694: -  level - level of fill, for ICC(k)

8696:    Notes:
8697:    Probably really in-place only when level of fill is zero, otherwise allocates
8698:    new space to store factored matrix and deletes previous memory.

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

8704:    Level: developer

8706:    Developer Note:
8707:    The Fortran interface is not autogenerated as the f90
8708:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

8710: .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8711: @*/
8712: PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8713: {
8721:   MatCheckPreallocated(mat, 1);
8722:   PetscUseTypeMethod(mat, iccfactor, row, info);
8723:   PetscObjectStateIncrease((PetscObject)mat);
8724:   return 0;
8725: }

8727: /*@
8728:    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8729:          ghosted ones.

8731:    Not Collective

8733:    Input Parameters:
8734: +  mat - the matrix
8735: -  diag - the diagonal values, including ghost ones

8737:    Level: developer

8739:    Notes:
8740:     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices

8742:     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`

8744: .seealso: `MatDiagonalScale()`
8745: @*/
8746: PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8747: {
8748:   PetscMPIInt size;


8755:   PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
8756:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8757:   if (size == 1) {
8758:     PetscInt n, m;
8759:     VecGetSize(diag, &n);
8760:     MatGetSize(mat, NULL, &m);
8761:     if (m == n) {
8762:       MatDiagonalScale(mat, NULL, diag);
8763:     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8764:   } else {
8765:     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8766:   }
8767:   PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
8768:   PetscObjectStateIncrease((PetscObject)mat);
8769:   return 0;
8770: }

8772: /*@
8773:    MatGetInertia - Gets the inertia from a factored matrix

8775:    Collective on mat

8777:    Input Parameter:
8778: .  mat - the matrix

8780:    Output Parameters:
8781: +   nneg - number of negative eigenvalues
8782: .   nzero - number of zero eigenvalues
8783: -   npos - number of positive eigenvalues

8785:    Level: advanced

8787:    Note:
8788:     Matrix must have been factored by `MatCholeskyFactor()`

8790: .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8791: @*/
8792: PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8793: {
8798:   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8799:   return 0;
8800: }

8802: /* ----------------------------------------------------------------*/
8803: /*@C
8804:    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors

8806:    Neighbor-wise Collective on mat

8808:    Input Parameters:
8809: +  mat - the factored matrix obtained with `MatGetFactor()`
8810: -  b - the right-hand-side vectors

8812:    Output Parameter:
8813: .  x - the result vectors

8815:    Note:
8816:    The vectors b and x cannot be the same.  I.e., one cannot
8817:    call `MatSolves`(A,x,x).

8819:    Level: developer

8821: .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8822: @*/
8823: PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
8824: {
8829:   if (!mat->rmap->N && !mat->cmap->N) return 0;

8831:   MatCheckPreallocated(mat, 1);
8832:   PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0);
8833:   PetscUseTypeMethod(mat, solves, b, x);
8834:   PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0);
8835:   return 0;
8836: }

8838: /*@
8839:    MatIsSymmetric - Test whether a matrix is symmetric

8841:    Collective on mat

8843:    Input Parameters:
8844: +  A - the matrix to test
8845: -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)

8847:    Output Parameters:
8848: .  flg - the result

8850:    Notes:
8851:     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results

8853:     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`

8855:     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8856:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

8858:    Level: intermediate

8860: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
8861:           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8862: @*/
8863: PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
8864: {

8868:   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8869:   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8870:   else {
8871:     if (!A->ops->issymmetric) {
8872:       MatType mattype;
8873:       MatGetType(A, &mattype);
8874:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8875:     }
8876:     PetscUseTypeMethod(A, issymmetric, tol, flg);
8877:     if (!tol) MatSetOption(A, MAT_SYMMETRIC, *flg);
8878:   }
8879:   return 0;
8880: }

8882: /*@
8883:    MatIsHermitian - Test whether a matrix is Hermitian

8885:    Collective on Mat

8887:    Input Parameters:
8888: +  A - the matrix to test
8889: -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)

8891:    Output Parameters:
8892: .  flg - the result

8894:    Level: intermediate

8896:    Notes:
8897:     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results

8899:     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`

8901:     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8902:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)

8904: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8905:           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8906: @*/
8907: PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
8908: {

8912:   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8913:   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8914:   else {
8915:     if (!A->ops->ishermitian) {
8916:       MatType mattype;
8917:       MatGetType(A, &mattype);
8918:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8919:     }
8920:     PetscUseTypeMethod(A, ishermitian, tol, flg);
8921:     if (!tol) MatSetOption(A, MAT_HERMITIAN, *flg);
8922:   }
8923:   return 0;
8924: }

8926: /*@
8927:    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state

8929:    Not Collective

8931:    Input Parameter:
8932: .  A - the matrix to check

8934:    Output Parameters:
8935: +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
8936: -  flg - the result (only valid if set is `PETSC_TRUE`)

8938:    Level: advanced

8940:    Notes:
8941:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
8942:    if you want it explicitly checked

8944:     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8945:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

8947: .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8948: @*/
8949: PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
8950: {
8954:   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8955:     *set = PETSC_TRUE;
8956:     *flg = PetscBool3ToBool(A->symmetric);
8957:   } else {
8958:     *set = PETSC_FALSE;
8959:   }
8960:   return 0;
8961: }

8963: /*@
8964:    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state

8966:    Not Collective

8968:    Input Parameter:
8969: .  A - the matrix to check

8971:    Output Parameters:
8972: +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
8973: -  flg - the result (only valid if set is `PETSC_TRUE`)

8975:    Level: advanced

8977:    Notes:
8978:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).

8980:    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
8981:    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)

8983: .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8984: @*/
8985: PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
8986: {
8990:   if (A->spd != PETSC_BOOL3_UNKNOWN) {
8991:     *set = PETSC_TRUE;
8992:     *flg = PetscBool3ToBool(A->spd);
8993:   } else {
8994:     *set = PETSC_FALSE;
8995:   }
8996:   return 0;
8997: }

8999: /*@
9000:    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state

9002:    Not Collective

9004:    Input Parameter:
9005: .  A - the matrix to check

9007:    Output Parameters:
9008: +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9009: -  flg - the result (only valid if set is `PETSC_TRUE`)

9011:    Level: advanced

9013:    Notes:
9014:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9015:    if you want it explicitly checked

9017:    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9018:    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9020: .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9021: @*/
9022: PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9023: {
9027:   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9028:     *set = PETSC_TRUE;
9029:     *flg = PetscBool3ToBool(A->hermitian);
9030:   } else {
9031:     *set = PETSC_FALSE;
9032:   }
9033:   return 0;
9034: }

9036: /*@
9037:    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric

9039:    Collective on Mat

9041:    Input Parameter:
9042: .  A - the matrix to test

9044:    Output Parameters:
9045: .  flg - the result

9047:    Notes:
9048:    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`

9050:    One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9051:    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9053:    Level: intermediate

9055: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9056: @*/
9057: PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9058: {
9061:   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9062:     *flg = PetscBool3ToBool(A->structurally_symmetric);
9063:   } else {
9064:     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9065:     MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg);
9066:   }
9067:   return 0;
9068: }

9070: /*@
9071:    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state

9073:    Not Collective

9075:    Input Parameter:
9076: .  A - the matrix to check

9078:    Output Parameters:
9079: +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9080: -  flg - the result (only valid if set is PETSC_TRUE)

9082:    Level: advanced

9084:    Notes:
9085:    One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9086:    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9088:    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)

9090: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9091: @*/
9092: PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9093: {
9097:   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9098:     *set = PETSC_TRUE;
9099:     *flg = PetscBool3ToBool(A->structurally_symmetric);
9100:   } else {
9101:     *set = PETSC_FALSE;
9102:   }
9103:   return 0;
9104: }

9106: /*@
9107:    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9108:        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process

9110:     Not collective

9112:    Input Parameter:
9113: .   mat - the matrix

9115:    Output Parameters:
9116: +   nstash   - the size of the stash
9117: .   reallocs - the number of additional mallocs incurred.
9118: .   bnstash   - the size of the block stash
9119: -   breallocs - the number of additional mallocs incurred.in the block stash

9121:    Level: advanced

9123: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9124: @*/
9125: PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9126: {
9127:   MatStashGetInfo_Private(&mat->stash, nstash, reallocs);
9128:   MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs);
9129:   return 0;
9130: }

9132: /*@C
9133:    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9134:    parallel layout, `PetscLayout` for rows and columns

9136:    Collective on mat

9138:    Input Parameter:
9139: .  mat - the matrix

9141:    Output Parameters:
9142: +   right - (optional) vector that the matrix can be multiplied against
9143: -   left - (optional) vector that the matrix vector product can be stored in

9145:    Notes:
9146:     The blocksize of the returned vectors is determined by the row and column block sizes set with `MatSetBlockSizes()` or the single blocksize (same for both) set by `MatSetBlockSize()`.

9148:     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed

9150:   Level: advanced

9152: .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9153: @*/
9154: PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9155: {
9158:   if (mat->ops->getvecs) {
9159:     PetscUseTypeMethod(mat, getvecs, right, left);
9160:   } else {
9161:     PetscInt rbs, cbs;
9162:     MatGetBlockSizes(mat, &rbs, &cbs);
9163:     if (right) {
9165:       VecCreate(PetscObjectComm((PetscObject)mat), right);
9166:       VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE);
9167:       VecSetBlockSize(*right, cbs);
9168:       VecSetType(*right, mat->defaultvectype);
9169: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9170:       if (mat->boundtocpu && mat->bindingpropagates) {
9171:         VecSetBindingPropagates(*right, PETSC_TRUE);
9172:         VecBindToCPU(*right, PETSC_TRUE);
9173:       }
9174: #endif
9175:       PetscLayoutReference(mat->cmap, &(*right)->map);
9176:     }
9177:     if (left) {
9179:       VecCreate(PetscObjectComm((PetscObject)mat), left);
9180:       VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE);
9181:       VecSetBlockSize(*left, rbs);
9182:       VecSetType(*left, mat->defaultvectype);
9183: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9184:       if (mat->boundtocpu && mat->bindingpropagates) {
9185:         VecSetBindingPropagates(*left, PETSC_TRUE);
9186:         VecBindToCPU(*left, PETSC_TRUE);
9187:       }
9188: #endif
9189:       PetscLayoutReference(mat->rmap, &(*left)->map);
9190:     }
9191:   }
9192:   return 0;
9193: }

9195: /*@C
9196:    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9197:      with default values.

9199:    Not Collective

9201:    Input Parameters:
9202: .    info - the `MatFactorInfo` data structure

9204:    Notes:
9205:     The solvers are generally used through the `KSP` and `PC` objects, for example
9206:           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`

9208:     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed

9210:    Level: developer

9212:    Developer Note:
9213:    The Fortran interface is not autogenerated as the f90
9214:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

9216: .seealso: `MatGetFactor()`, `MatFactorInfo`
9217: @*/
9218: PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9219: {
9220:   PetscMemzero(info, sizeof(MatFactorInfo));
9221:   return 0;
9222: }

9224: /*@
9225:    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed

9227:    Collective on mat

9229:    Input Parameters:
9230: +  mat - the factored matrix
9231: -  is - the index set defining the Schur indices (0-based)

9233:    Notes:
9234:     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.

9236:    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.

9238:    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`

9240:    Level: advanced

9242: .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9243:           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`

9245: @*/
9246: PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9247: {
9248:   PetscErrorCode (*f)(Mat, IS);

9256:   PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f);
9258:   MatDestroy(&mat->schur);
9259:   (*f)(mat, is);
9261:   return 0;
9262: }

9264: /*@
9265:   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step

9267:    Logically Collective on mat

9269:    Input Parameters:
9270: +  F - the factored matrix obtained by calling `MatGetFactor()`
9271: .  S - location where to return the Schur complement, can be NULL
9272: -  status - the status of the Schur complement matrix, can be NULL

9274:    Notes:
9275:    You must call `MatFactorSetSchurIS()` before calling this routine.

9277:    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`

9279:    The routine provides a copy of the Schur matrix stored within the solver data structures.
9280:    The caller must destroy the object when it is no longer needed.
9281:    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.

9283:    Use `MatFactorGetSchurComplement()` to get access to the Schur complement matrix inside the factored matrix instead of making a copy of it (which this function does)

9285:    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.

9287:    Developer Note:
9288:     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9289:    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.

9291:    Level: advanced

9293: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9294: @*/
9295: PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9296: {
9300:   if (S) {
9301:     PetscErrorCode (*f)(Mat, Mat *);

9303:     PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f);
9304:     if (f) {
9305:       (*f)(F, S);
9306:     } else {
9307:       MatDuplicate(F->schur, MAT_COPY_VALUES, S);
9308:     }
9309:   }
9310:   if (status) *status = F->schur_status;
9311:   return 0;
9312: }

9314: /*@
9315:   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix

9317:    Logically Collective on mat

9319:    Input Parameters:
9320: +  F - the factored matrix obtained by calling `MatGetFactor()`
9321: .  *S - location where to return the Schur complement, can be NULL
9322: -  status - the status of the Schur complement matrix, can be NULL

9324:    Notes:
9325:    You must call `MatFactorSetSchurIS()` before calling this routine.

9327:    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`

9329:    The routine returns a the Schur Complement stored within the data strutures of the solver.

9331:    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.

9333:    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.

9335:    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix

9337:    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.

9339:    Level: advanced

9341: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9342: @*/
9343: PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9344: {
9348:   if (S) *S = F->schur;
9349:   if (status) *status = F->schur_status;
9350:   return 0;
9351: }

9353: /*@
9354:   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`

9356:    Logically Collective on mat

9358:    Input Parameters:
9359: +  F - the factored matrix obtained by calling `MatGetFactor()`
9360: .  *S - location where the Schur complement is stored
9361: -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)

9363:    Level: advanced

9365: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9366: @*/
9367: PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9368: {
9370:   if (S) {
9372:     *S = NULL;
9373:   }
9374:   F->schur_status = status;
9375:   MatFactorUpdateSchurStatus_Private(F);
9376:   return 0;
9377: }

9379: /*@
9380:   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step

9382:    Logically Collective on mat

9384:    Input Parameters:
9385: +  F - the factored matrix obtained by calling `MatGetFactor()`
9386: .  rhs - location where the right hand side of the Schur complement system is stored
9387: -  sol - location where the solution of the Schur complement system has to be returned

9389:    Notes:
9390:    The sizes of the vectors should match the size of the Schur complement

9392:    Must be called after `MatFactorSetSchurIS()`

9394:    Level: advanced

9396: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9397: @*/
9398: PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9399: {
9408:   MatFactorFactorizeSchurComplement(F);
9409:   switch (F->schur_status) {
9410:   case MAT_FACTOR_SCHUR_FACTORED:
9411:     MatSolveTranspose(F->schur, rhs, sol);
9412:     break;
9413:   case MAT_FACTOR_SCHUR_INVERTED:
9414:     MatMultTranspose(F->schur, rhs, sol);
9415:     break;
9416:   default:
9417:     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9418:   }
9419:   return 0;
9420: }

9422: /*@
9423:   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step

9425:    Logically Collective on mat

9427:    Input Parameters:
9428: +  F - the factored matrix obtained by calling `MatGetFactor()`
9429: .  rhs - location where the right hand side of the Schur complement system is stored
9430: -  sol - location where the solution of the Schur complement system has to be returned

9432:    Notes:
9433:    The sizes of the vectors should match the size of the Schur complement

9435:    Must be called after `MatFactorSetSchurIS()`

9437:    Level: advanced

9439: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9440: @*/
9441: PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9442: {
9451:   MatFactorFactorizeSchurComplement(F);
9452:   switch (F->schur_status) {
9453:   case MAT_FACTOR_SCHUR_FACTORED:
9454:     MatSolve(F->schur, rhs, sol);
9455:     break;
9456:   case MAT_FACTOR_SCHUR_INVERTED:
9457:     MatMult(F->schur, rhs, sol);
9458:     break;
9459:   default:
9460:     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9461:   }
9462:   return 0;
9463: }

9465: /*@
9466:   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step

9468:    Logically Collective on F

9470:    Input Parameters:
9471: .  F - the factored matrix obtained by calling `MatGetFactor()`

9473:    Notes:
9474:     Must be called after `MatFactorSetSchurIS()`.

9476:    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.

9478:    Level: advanced

9480: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9481: @*/
9482: PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9483: {
9486:   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) return 0;
9487:   MatFactorFactorizeSchurComplement(F);
9488:   MatFactorInvertSchurComplement_Private(F);
9489:   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9490:   return 0;
9491: }

9493: /*@
9494:   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step

9496:    Logically Collective on mat

9498:    Input Parameters:
9499: .  F - the factored matrix obtained by calling `MatGetFactor()`

9501:    Note:
9502:     Must be called after `MatFactorSetSchurIS()`

9504:    Level: advanced

9506: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9507: @*/
9508: PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9509: {
9512:   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) return 0;
9513:   MatFactorFactorizeSchurComplement_Private(F);
9514:   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9515:   return 0;
9516: }

9518: /*@
9519:    MatPtAP - Creates the matrix product C = P^T * A * P

9521:    Neighbor-wise Collective on A

9523:    Input Parameters:
9524: +  A - the matrix
9525: .  P - the projection matrix
9526: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9527: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9528:           if the result is a dense matrix this is irrelevant

9530:    Output Parameters:
9531: .  C - the product matrix

9533:    Notes:
9534:    C will be created and must be destroyed by the user with `MatDestroy()`.

9536:    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done

9538:    Developer Note:
9539:    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.

9541:    Level: intermediate

9543: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9544: @*/
9545: PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9546: {
9547:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);

9550:   if (scall == MAT_INITIAL_MATRIX) {
9551:     MatProductCreate(A, P, NULL, C);
9552:     MatProductSetType(*C, MATPRODUCT_PtAP);
9553:     MatProductSetAlgorithm(*C, "default");
9554:     MatProductSetFill(*C, fill);

9556:     (*C)->product->api_user = PETSC_TRUE;
9557:     MatProductSetFromOptions(*C);
9559:     MatProductSymbolic(*C);
9560:   } else { /* scall == MAT_REUSE_MATRIX */
9561:     MatProductReplaceMats(A, P, NULL, *C);
9562:   }

9564:   MatProductNumeric(*C);
9565:   (*C)->symmetric = A->symmetric;
9566:   (*C)->spd       = A->spd;
9567:   return 0;
9568: }

9570: /*@
9571:    MatRARt - Creates the matrix product C = R * A * R^T

9573:    Neighbor-wise Collective on A

9575:    Input Parameters:
9576: +  A - the matrix
9577: .  R - the projection matrix
9578: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9579: -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9580:           if the result is a dense matrix this is irrelevant

9582:    Output Parameters:
9583: .  C - the product matrix

9585:    Notes:
9586:    C will be created and must be destroyed by the user with `MatDestroy()`.

9588:    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done

9590:    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9591:    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9592:    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9593:    We recommend using MatPtAP().

9595:    Level: intermediate

9597: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9598: @*/
9599: PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9600: {
9601:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);

9604:   if (scall == MAT_INITIAL_MATRIX) {
9605:     MatProductCreate(A, R, NULL, C);
9606:     MatProductSetType(*C, MATPRODUCT_RARt);
9607:     MatProductSetAlgorithm(*C, "default");
9608:     MatProductSetFill(*C, fill);

9610:     (*C)->product->api_user = PETSC_TRUE;
9611:     MatProductSetFromOptions(*C);
9613:     MatProductSymbolic(*C);
9614:   } else { /* scall == MAT_REUSE_MATRIX */
9615:     MatProductReplaceMats(A, R, NULL, *C);
9616:   }

9618:   MatProductNumeric(*C);
9619:   if (A->symmetric == PETSC_BOOL3_TRUE) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9620:   return 0;
9621: }

9623: static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9624: {

9627:   if (scall == MAT_INITIAL_MATRIX) {
9628:     PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]);
9629:     MatProductCreate(A, B, NULL, C);
9630:     MatProductSetType(*C, ptype);
9631:     MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT);
9632:     MatProductSetFill(*C, fill);

9634:     (*C)->product->api_user = PETSC_TRUE;
9635:     MatProductSetFromOptions(*C);
9636:     MatProductSymbolic(*C);
9637:   } else { /* scall == MAT_REUSE_MATRIX */
9638:     Mat_Product *product = (*C)->product;
9639:     PetscBool    isdense;

9641:     PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "");
9642:     if (isdense && product && product->type != ptype) {
9643:       MatProductClear(*C);
9644:       product = NULL;
9645:     }
9646:     PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]);
9647:     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9648:       if (isdense) {
9649:         MatProductCreate_Private(A, B, NULL, *C);
9650:         product           = (*C)->product;
9651:         product->fill     = fill;
9652:         product->api_user = PETSC_TRUE;
9653:         product->clear    = PETSC_TRUE;

9655:         MatProductSetType(*C, ptype);
9656:         MatProductSetFromOptions(*C);
9658:         MatProductSymbolic(*C);
9659:       } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9660:     } else { /* user may change input matrices A or B when REUSE */
9661:       MatProductReplaceMats(A, B, NULL, *C);
9662:     }
9663:   }
9664:   MatProductNumeric(*C);
9665:   return 0;
9666: }

9668: /*@
9669:    MatMatMult - Performs matrix-matrix multiplication C=A*B.

9671:    Neighbor-wise Collective on A

9673:    Input Parameters:
9674: +  A - the left matrix
9675: .  B - the right matrix
9676: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9677: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9678:           if the result is a dense matrix this is irrelevant

9680:    Output Parameters:
9681: .  C - the product matrix

9683:    Notes:
9684:    Unless scall is `MAT_REUSE_MATRIX` C will be created.

9686:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call and C was obtained from a previous
9687:    call to this function with `MAT_INITIAL_MATRIX`.

9689:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.

9691:    In the special case where matrix B (and hence C) are dense you can create the correctly sized matrix C yourself and then call this routine with `MAT_REUSE_MATRIX`,
9692:    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.

9694:    Example of Usage:
9695: .vb
9696:      MatProductCreate(A,B,NULL,&C);
9697:      MatProductSetType(C,MATPRODUCT_AB);
9698:      MatProductSymbolic(C);
9699:      MatProductNumeric(C); // compute C=A * B
9700:      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9701:      MatProductNumeric(C);
9702:      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9703:      MatProductNumeric(C);
9704: .ve

9706:    Level: intermediate

9708: .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9709: @*/
9710: PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9711: {
9712:   MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C);
9713:   return 0;
9714: }

9716: /*@
9717:    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.

9719:    Neighbor-wise Collective on A

9721:    Input Parameters:
9722: +  A - the left matrix
9723: .  B - the right matrix
9724: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9725: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known

9727:    Output Parameters:
9728: .  C - the product matrix

9730:    Notes:
9731:    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.

9733:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call

9735:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9736:    actually needed.

9738:    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9739:    and for pairs of `MATMPIDENSE` matrices.

9741:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`

9743:    Options Database Keys:
9744: .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9745:               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9746:               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.

9748:    Level: intermediate

9750: .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9751: @*/
9752: PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9753: {
9754:   MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C);
9755:   if (A == B) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9756:   return 0;
9757: }

9759: /*@
9760:    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.

9762:    Neighbor-wise Collective on A

9764:    Input Parameters:
9765: +  A - the left matrix
9766: .  B - the right matrix
9767: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9768: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known

9770:    Output Parameters:
9771: .  C - the product matrix

9773:    Notes:
9774:    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.

9776:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.

9778:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`

9780:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9781:    actually needed.

9783:    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9784:    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.

9786:    Level: intermediate

9788: .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9789: @*/
9790: PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9791: {
9792:   MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C);
9793:   return 0;
9794: }

9796: /*@
9797:    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.

9799:    Neighbor-wise Collective on A

9801:    Input Parameters:
9802: +  A - the left matrix
9803: .  B - the middle matrix
9804: .  C - the right matrix
9805: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9806: -  fill - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DEFAULT` if you do not have a good estimate
9807:           if the result is a dense matrix this is irrelevant

9809:    Output Parameters:
9810: .  D - the product matrix

9812:    Notes:
9813:    Unless scall is `MAT_REUSE_MATRIX` D will be created.

9815:    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call

9817:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`

9819:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9820:    actually needed.

9822:    If you have many matrices with the same non-zero structure to multiply, you
9823:    should use `MAT_REUSE_MATRIX` in all calls but the first

9825:    Level: intermediate

9827: .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9828: @*/
9829: PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
9830: {
9831:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);

9834:   if (scall == MAT_INITIAL_MATRIX) {
9835:     MatProductCreate(A, B, C, D);
9836:     MatProductSetType(*D, MATPRODUCT_ABC);
9837:     MatProductSetAlgorithm(*D, "default");
9838:     MatProductSetFill(*D, fill);

9840:     (*D)->product->api_user = PETSC_TRUE;
9841:     MatProductSetFromOptions(*D);
9843:                ((PetscObject)C)->type_name);
9844:     MatProductSymbolic(*D);
9845:   } else { /* user may change input matrices when REUSE */
9846:     MatProductReplaceMats(A, B, C, *D);
9847:   }
9848:   MatProductNumeric(*D);
9849:   return 0;
9850: }

9852: /*@
9853:    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.

9855:    Collective on mat

9857:    Input Parameters:
9858: +  mat - the matrix
9859: .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9860: .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
9861: -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

9863:    Output Parameter:
9864: .  matredundant - redundant matrix

9866:    Notes:
9867:    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
9868:    original matrix has not changed from that last call to MatCreateRedundantMatrix().

9870:    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9871:    calling it.

9873:    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.

9875:    Level: advanced

9877: .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
9878: @*/
9879: PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
9880: {
9881:   MPI_Comm       comm;
9882:   PetscMPIInt    size;
9883:   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9884:   Mat_Redundant *redund     = NULL;
9885:   PetscSubcomm   psubcomm   = NULL;
9886:   MPI_Comm       subcomm_in = subcomm;
9887:   Mat           *matseq;
9888:   IS             isrow, iscol;
9889:   PetscBool      newsubcomm = PETSC_FALSE;

9892:   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9895:   }

9897:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
9898:   if (size == 1 || nsubcomm == 1) {
9899:     if (reuse == MAT_INITIAL_MATRIX) {
9900:       MatDuplicate(mat, MAT_COPY_VALUES, matredundant);
9901:     } else {
9903:       MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN);
9904:     }
9905:     return 0;
9906:   }

9910:   MatCheckPreallocated(mat, 1);

9912:   PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0);
9913:   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9914:     /* create psubcomm, then get subcomm */
9915:     PetscObjectGetComm((PetscObject)mat, &comm);
9916:     MPI_Comm_size(comm, &size);

9919:     PetscSubcommCreate(comm, &psubcomm);
9920:     PetscSubcommSetNumber(psubcomm, nsubcomm);
9921:     PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS);
9922:     PetscSubcommSetFromOptions(psubcomm);
9923:     PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL);
9924:     newsubcomm = PETSC_TRUE;
9925:     PetscSubcommDestroy(&psubcomm);
9926:   }

9928:   /* get isrow, iscol and a local sequential matrix matseq[0] */
9929:   if (reuse == MAT_INITIAL_MATRIX) {
9930:     mloc_sub = PETSC_DECIDE;
9931:     nloc_sub = PETSC_DECIDE;
9932:     if (bs < 1) {
9933:       PetscSplitOwnership(subcomm, &mloc_sub, &M);
9934:       PetscSplitOwnership(subcomm, &nloc_sub, &N);
9935:     } else {
9936:       PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M);
9937:       PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N);
9938:     }
9939:     MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm);
9940:     rstart = rend - mloc_sub;
9941:     ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow);
9942:     ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol);
9943:   } else { /* reuse == MAT_REUSE_MATRIX */
9945:     /* retrieve subcomm */
9946:     PetscObjectGetComm((PetscObject)(*matredundant), &subcomm);
9947:     redund = (*matredundant)->redundant;
9948:     isrow  = redund->isrow;
9949:     iscol  = redund->iscol;
9950:     matseq = redund->matseq;
9951:   }
9952:   MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq);

9954:   /* get matredundant over subcomm */
9955:   if (reuse == MAT_INITIAL_MATRIX) {
9956:     MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant);

9958:     /* create a supporting struct and attach it to C for reuse */
9959:     PetscNew(&redund);
9960:     (*matredundant)->redundant = redund;
9961:     redund->isrow              = isrow;
9962:     redund->iscol              = iscol;
9963:     redund->matseq             = matseq;
9964:     if (newsubcomm) {
9965:       redund->subcomm = subcomm;
9966:     } else {
9967:       redund->subcomm = MPI_COMM_NULL;
9968:     }
9969:   } else {
9970:     MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant);
9971:   }
9972: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9973:   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
9974:     MatBindToCPU(*matredundant, PETSC_TRUE);
9975:     MatSetBindingPropagates(*matredundant, PETSC_TRUE);
9976:   }
9977: #endif
9978:   PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0);
9979:   return 0;
9980: }

9982: /*@C
9983:    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
9984:    a given `Mat`. Each submatrix can span multiple procs.

9986:    Collective on mat

9988:    Input Parameters:
9989: +  mat - the matrix
9990: .  subcomm - the subcommunicator obtained by MPI_Com_split(comm)
9991: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

9993:    Output Parameter:
9994: .  subMat - 'parallel submatrices each spans a given subcomm

9996:   Notes:
9997:   The submatrix partition across processors is dictated by 'subComm' a
9998:   communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
9999:   is not restriced to be grouped with consecutive original ranks.

10001:   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10002:   map directly to the layout of the original matrix [wrt the local
10003:   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10004:   into the 'DiagonalMat' of the subMat, hence it is used directly from
10005:   the subMat. However the offDiagMat looses some columns - and this is
10006:   reconstructed with `MatSetValues()`

10008:   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks

10010:   Level: advanced

10012: .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10013: @*/
10014: PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10015: {
10016:   PetscMPIInt commsize, subCommSize;

10018:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize);
10019:   MPI_Comm_size(subComm, &subCommSize);

10023:   PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10024:   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10025:   PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10026:   return 0;
10027: }

10029: /*@
10030:    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering

10032:    Not Collective

10034:    Input Parameters:
10035: +  mat - matrix to extract local submatrix from
10036: .  isrow - local row indices for submatrix
10037: -  iscol - local column indices for submatrix

10039:    Output Parameter:
10040: .  submat - the submatrix

10042:    Level: intermediate

10044:    Notes:
10045:    The submat should be returned with `MatRestoreLocalSubMatrix()`.

10047:    Depending on the format of mat, the returned submat may not implement `MatMult()`.  Its communicator may be
10048:    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.

10050:    The submat always implements `MatSetValuesLocal()`.  If isrow and iscol have the same block size, then
10051:    `MatSetValuesBlockedLocal()` will also be implemented.

10053:    The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10054:    Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.

10056: .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10057: @*/
10058: PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10059: {

10067:   if (mat->ops->getlocalsubmatrix) {
10068:     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10069:   } else {
10070:     MatCreateLocalRef(mat, isrow, iscol, submat);
10071:   }
10072:   return 0;
10073: }

10075: /*@
10076:    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`

10078:    Not Collective

10080:    Input Parameters:
10081: +  mat - matrix to extract local submatrix from
10082: .  isrow - local row indices for submatrix
10083: .  iscol - local column indices for submatrix
10084: -  submat - the submatrix

10086:    Level: intermediate

10088: .seealso: `MatGetLocalSubMatrix()`
10089: @*/
10090: PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10091: {

10099:   if (mat->ops->restorelocalsubmatrix) {
10100:     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10101:   } else {
10102:     MatDestroy(submat);
10103:   }
10104:   *submat = NULL;
10105:   return 0;
10106: }

10108: /* --------------------------------------------------------*/
10109: /*@
10110:    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix

10112:    Collective on mat

10114:    Input Parameter:
10115: .  mat - the matrix

10117:    Output Parameter:
10118: .  is - if any rows have zero diagonals this contains the list of them

10120:    Level: developer

10122: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10123: @*/
10124: PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10125: {

10131:   if (!mat->ops->findzerodiagonals) {
10132:     Vec                diag;
10133:     const PetscScalar *a;
10134:     PetscInt          *rows;
10135:     PetscInt           rStart, rEnd, r, nrow = 0;

10137:     MatCreateVecs(mat, &diag, NULL);
10138:     MatGetDiagonal(mat, diag);
10139:     MatGetOwnershipRange(mat, &rStart, &rEnd);
10140:     VecGetArrayRead(diag, &a);
10141:     for (r = 0; r < rEnd - rStart; ++r)
10142:       if (a[r] == 0.0) ++nrow;
10143:     PetscMalloc1(nrow, &rows);
10144:     nrow = 0;
10145:     for (r = 0; r < rEnd - rStart; ++r)
10146:       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10147:     VecRestoreArrayRead(diag, &a);
10148:     VecDestroy(&diag);
10149:     ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is);
10150:   } else {
10151:     PetscUseTypeMethod(mat, findzerodiagonals, is);
10152:   }
10153:   return 0;
10154: }

10156: /*@
10157:    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)

10159:    Collective on mat

10161:    Input Parameter:
10162: .  mat - the matrix

10164:    Output Parameter:
10165: .  is - contains the list of rows with off block diagonal entries

10167:    Level: developer

10169: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10170: @*/
10171: PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10172: {

10178:   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10179:   return 0;
10180: }

10182: /*@C
10183:   MatInvertBlockDiagonal - Inverts the block diagonal entries.

10185:   Collective on mat

10187:   Input Parameters:
10188: . mat - the matrix

10190:   Output Parameters:
10191: . values - the block inverses in column major order (FORTRAN-like)

10193:    Notes:
10194:    The size of the blocks is determined by the block size of the matrix.

10196:    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case

10198:    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size

10200:    Fortran Note:
10201:      This routine is not available from Fortran.

10203:   Level: advanced

10205: .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10206: @*/
10207: PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10208: {
10212:   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10213:   return 0;
10214: }

10216: /*@C
10217:   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.

10219:   Collective on mat

10221:   Input Parameters:
10222: + mat - the matrix
10223: . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10224: - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`

10226:   Output Parameters:
10227: . values - the block inverses in column major order (FORTRAN-like)

10229:   Notes:
10230:   Use `MatInvertBlockDiagonal()` if all blocks have the same size

10232:   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case

10234:   Fortran Note:
10235:   This routine is not available from Fortran.

10237:   Level: advanced

10239: .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10240: @*/
10241: PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10242: {
10246:   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10247:   return 0;
10248: }

10250: /*@
10251:   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A

10253:   Collective on Mat

10255:   Input Parameters:
10256: + A - the matrix
10257: - C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.

10259:   Note:
10260:   The blocksize of the matrix is used to determine the blocks on the diagonal of C

10262:   Level: advanced

10264: .seealso: `MatInvertBlockDiagonal()`
10265: @*/
10266: PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10267: {
10268:   const PetscScalar *vals;
10269:   PetscInt          *dnnz;
10270:   PetscInt           m, rstart, rend, bs, i, j;

10272:   MatInvertBlockDiagonal(A, &vals);
10273:   MatGetBlockSize(A, &bs);
10274:   MatGetLocalSize(A, &m, NULL);
10275:   MatSetLayouts(C, A->rmap, A->cmap);
10276:   PetscMalloc1(m / bs, &dnnz);
10277:   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10278:   MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL);
10279:   PetscFree(dnnz);
10280:   MatGetOwnershipRange(C, &rstart, &rend);
10281:   MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE);
10282:   for (i = rstart / bs; i < rend / bs; i++) MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES);
10283:   MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY);
10284:   MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY);
10285:   MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE);
10286:   return 0;
10287: }

10289: /*@C
10290:     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10291:     via `MatTransposeColoringCreate()`.

10293:     Collective on c

10295:     Input Parameter:
10296: .   c - coloring context

10298:     Level: intermediate

10300: .seealso: `MatTransposeColoringCreate()`
10301: @*/
10302: PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10303: {
10304:   MatTransposeColoring matcolor = *c;

10306:   if (!matcolor) return 0;
10307:   if (--((PetscObject)matcolor)->refct > 0) {
10308:     matcolor = NULL;
10309:     return 0;
10310:   }

10312:   PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow);
10313:   PetscFree(matcolor->rows);
10314:   PetscFree(matcolor->den2sp);
10315:   PetscFree(matcolor->colorforcol);
10316:   PetscFree(matcolor->columns);
10317:   if (matcolor->brows > 0) PetscFree(matcolor->lstart);
10318:   PetscHeaderDestroy(c);
10319:   return 0;
10320: }

10322: /*@C
10323:     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10324:     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10325:     `MatTransposeColoring` to sparse B.

10327:     Collective on coloring

10329:     Input Parameters:
10330: +   B - sparse matrix B
10331: .   Btdense - symbolic dense matrix B^T
10332: -   coloring - coloring context created with `MatTransposeColoringCreate()`

10334:     Output Parameter:
10335: .   Btdense - dense matrix B^T

10337:     Level: developer

10339:     Note:
10340:     These are used internally for some implementations of `MatRARt()`

10342: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`

10344: @*/
10345: PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10346: {

10351:   (B->ops->transcoloringapplysptoden)(coloring, B, Btdense);
10352:   return 0;
10353: }

10355: /*@C
10356:     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10357:     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10358:     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10359:     Csp from Cden.

10361:     Collective on matcoloring

10363:     Input Parameters:
10364: +   coloring - coloring context created with `MatTransposeColoringCreate()`
10365: -   Cden - matrix product of a sparse matrix and a dense matrix Btdense

10367:     Output Parameter:
10368: .   Csp - sparse matrix

10370:     Level: developer

10372:     Note:
10373:     These are used internally for some implementations of `MatRARt()`

10375: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`

10377: @*/
10378: PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10379: {

10384:   (Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp);
10385:   MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY);
10386:   MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY);
10387:   return 0;
10388: }

10390: /*@C
10391:    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.

10393:    Collective on mat

10395:    Input Parameters:
10396: +  mat - the matrix product C
10397: -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`

10399:     Output Parameter:
10400: .   color - the new coloring context

10402:     Level: intermediate

10404: .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10405:           `MatTransColoringApplyDenToSp()`
10406: @*/
10407: PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10408: {
10409:   MatTransposeColoring c;
10410:   MPI_Comm             comm;

10412:   PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10413:   PetscObjectGetComm((PetscObject)mat, &comm);
10414:   PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL);

10416:   c->ctype = iscoloring->ctype;
10417:   if (mat->ops->transposecoloringcreate) {
10418:     PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10419:   } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);

10421:   *color = c;
10422:   PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10423:   return 0;
10424: }

10426: /*@
10427:       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10428:         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10429:         same, otherwise it will be larger

10431:      Not Collective

10433:   Input Parameter:
10434: .    A  - the matrix

10436:   Output Parameter:
10437: .    state - the current state

10439:   Notes:
10440:     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10441:          different matrices

10443:     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix

10445:     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.

10447:   Level: intermediate

10449: .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10450: @*/
10451: PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10452: {
10454:   *state = mat->nonzerostate;
10455:   return 0;
10456: }

10458: /*@
10459:       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10460:                  matrices from each processor

10462:     Collective

10464:    Input Parameters:
10465: +    comm - the communicators the parallel matrix will live on
10466: .    seqmat - the input sequential matrices
10467: .    n - number of local columns (or `PETSC_DECIDE`)
10468: -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

10470:    Output Parameter:
10471: .    mpimat - the parallel matrix generated

10473:     Level: developer

10475:    Note:
10476:     The number of columns of the matrix in EACH processor MUST be the same.

10478: .seealso: `Mat`
10479: @*/
10480: PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10481: {
10482:   PetscMPIInt size;

10484:   MPI_Comm_size(comm, &size);
10485:   if (size == 1) {
10486:     if (reuse == MAT_INITIAL_MATRIX) {
10487:       MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat);
10488:     } else {
10489:       MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN);
10490:     }
10491:     return 0;
10492:   }


10496:   PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0);
10497:   (*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat);
10498:   PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0);
10499:   return 0;
10500: }

10502: /*@
10503:      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.

10505:     Collective on A

10507:    Input Parameters:
10508: +    A   - the matrix to create subdomains from
10509: -    N   - requested number of subdomains

10511:    Output Parameters:
10512: +    n   - number of subdomains resulting on this rank
10513: -    iss - `IS` list with indices of subdomains on this rank

10515:     Level: advanced

10517:     Note:
10518:     The number of subdomains must be smaller than the communicator size

10520: .seealso: `Mat`, `IS`
10521: @*/
10522: PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10523: {
10524:   MPI_Comm    comm, subcomm;
10525:   PetscMPIInt size, rank, color;
10526:   PetscInt    rstart, rend, k;

10528:   PetscObjectGetComm((PetscObject)A, &comm);
10529:   MPI_Comm_size(comm, &size);
10530:   MPI_Comm_rank(comm, &rank);
10532:   *n    = 1;
10533:   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10534:   color = rank / k;
10535:   MPI_Comm_split(comm, color, rank, &subcomm);
10536:   PetscMalloc1(1, iss);
10537:   MatGetOwnershipRange(A, &rstart, &rend);
10538:   ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]);
10539:   MPI_Comm_free(&subcomm);
10540:   return 0;
10541: }

10543: /*@
10544:    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.

10546:    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10547:    If they are not the same, uses `MatMatMatMult()`.

10549:    Once the coarse grid problem is constructed, correct for interpolation operators
10550:    that are not of full rank, which can legitimately happen in the case of non-nested
10551:    geometric multigrid.

10553:    Input Parameters:
10554: +  restrct - restriction operator
10555: .  dA - fine grid matrix
10556: .  interpolate - interpolation operator
10557: .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10558: -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate

10560:    Output Parameters:
10561: .  A - the Galerkin coarse matrix

10563:    Options Database Key:
10564: .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used

10566:    Level: developer

10568: .seealso: `MatPtAP()`, `MatMatMatMult()`
10569: @*/
10570: PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10571: {
10572:   IS  zerorows;
10573:   Vec diag;

10576:   /* Construct the coarse grid matrix */
10577:   if (interpolate == restrct) {
10578:     MatPtAP(dA, interpolate, reuse, fill, A);
10579:   } else {
10580:     MatMatMatMult(restrct, dA, interpolate, reuse, fill, A);
10581:   }

10583:   /* If the interpolation matrix is not of full rank, A will have zero rows.
10584:      This can legitimately happen in the case of non-nested geometric multigrid.
10585:      In that event, we set the rows of the matrix to the rows of the identity,
10586:      ignoring the equations (as the RHS will also be zero). */

10588:   MatFindZeroRows(*A, &zerorows);

10590:   if (zerorows != NULL) { /* if there are any zero rows */
10591:     MatCreateVecs(*A, &diag, NULL);
10592:     MatGetDiagonal(*A, diag);
10593:     VecISSet(diag, zerorows, 1.0);
10594:     MatDiagonalSet(*A, diag, INSERT_VALUES);
10595:     VecDestroy(&diag);
10596:     ISDestroy(&zerorows);
10597:   }
10598:   return 0;
10599: }

10601: /*@C
10602:     MatSetOperation - Allows user to set a matrix operation for any matrix type

10604:    Logically Collective on mat

10606:     Input Parameters:
10607: +   mat - the matrix
10608: .   op - the name of the operation
10609: -   f - the function that provides the operation

10611:    Level: developer

10613:     Usage:
10614: $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10615: $      MatCreateXXX(comm,...&A;
10616: $      MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult;

10618:     Notes:
10619:     See the file include/petscmat.h for a complete list of matrix
10620:     operations, which all have the form MATOP_<OPERATION>, where
10621:     <OPERATION> is the name (in all capital letters) of the
10622:     user interface routine (e.g., MatMult() -> MATOP_MULT).

10624:     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10625:     sequence as the usual matrix interface routines, since they
10626:     are intended to be accessed via the usual matrix interface
10627:     routines, e.g.,
10628: $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)

10630:     In particular each function MUST return an error code of 0 on success and
10631:     nonzero on failure.

10633:     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.

10635: .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10636: @*/
10637: PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10638: {
10640:   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10641:   (((void (**)(void))mat->ops)[op]) = f;
10642:   return 0;
10643: }

10645: /*@C
10646:     MatGetOperation - Gets a matrix operation for any matrix type.

10648:     Not Collective

10650:     Input Parameters:
10651: +   mat - the matrix
10652: -   op - the name of the operation

10654:     Output Parameter:
10655: .   f - the function that provides the operation

10657:     Level: developer

10659:     Usage:
10660: $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10661: $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);

10663:     Notes:
10664:     See the file include/petscmat.h for a complete list of matrix
10665:     operations, which all have the form MATOP_<OPERATION>, where
10666:     <OPERATION> is the name (in all capital letters) of the
10667:     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).

10669:     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.

10671: .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10672: @*/
10673: PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10674: {
10676:   *f = (((void (**)(void))mat->ops)[op]);
10677:   return 0;
10678: }

10680: /*@
10681:     MatHasOperation - Determines whether the given matrix supports the particular operation.

10683:    Not Collective

10685:    Input Parameters:
10686: +  mat - the matrix
10687: -  op - the operation, for example, `MATOP_GET_DIAGONAL`

10689:    Output Parameter:
10690: .  has - either `PETSC_TRUE` or `PETSC_FALSE`

10692:    Level: advanced

10694:    Note:
10695:    See the file include/petscmat.h for a complete list of matrix
10696:    operations, which all have the form MATOP_<OPERATION>, where
10697:    <OPERATION> is the name (in all capital letters) of the
10698:    user-level routine.  E.g., `MatNorm()` -> `MATOP_NORM`.

10700: .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10701: @*/
10702: PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10703: {
10706:   if (mat->ops->hasoperation) {
10707:     PetscUseTypeMethod(mat, hasoperation, op, has);
10708:   } else {
10709:     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10710:     else {
10711:       *has = PETSC_FALSE;
10712:       if (op == MATOP_CREATE_SUBMATRIX) {
10713:         PetscMPIInt size;

10715:         MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
10716:         if (size == 1) MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has);
10717:       }
10718:     }
10719:   }
10720:   return 0;
10721: }

10723: /*@
10724:     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent

10726:    Collective on mat

10728:    Input Parameters:
10729: .  mat - the matrix

10731:    Output Parameter:
10732: .  cong - either `PETSC_TRUE` or `PETSC_FALSE`

10734:    Level: beginner

10736: .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10737: @*/
10738: PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10739: {
10743:   if (!mat->rmap || !mat->cmap) {
10744:     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10745:     return 0;
10746:   }
10747:   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10748:     PetscLayoutSetUp(mat->rmap);
10749:     PetscLayoutSetUp(mat->cmap);
10750:     PetscLayoutCompare(mat->rmap, mat->cmap, cong);
10751:     if (*cong) mat->congruentlayouts = 1;
10752:     else mat->congruentlayouts = 0;
10753:   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10754:   return 0;
10755: }

10757: PetscErrorCode MatSetInf(Mat A)
10758: {
10759:   PetscUseTypeMethod(A, setinf);
10760:   return 0;
10761: }

10763: /*C
10764:    MatCreateGraph - create a scalar matrix (that is a matrix with one vertex for each block vertex in the original matrix), for use in graph algorithms
10765:    and possibly removes small values from the graph structure.

10767:    Collective on mat

10769:    Input Parameters:
10770: +  A - the matrix
10771: .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
10772: .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
10773: -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value

10775:    Output Parameter:
10776: .  graph - the resulting graph

10778:    Level: advanced

10780: .seealso: `MatCreate()`, `PCGAMG`
10781: */
10782: PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
10783: {
10787:   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
10788:   return 0;
10789: }