Actual source code: matrix.c

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

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

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

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

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

 50: /*@
 51:    MatSetRandom - Sets all components of a matrix to random numbers.

 53:    Logically Collective

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

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

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

 70:    Level: intermediate

 72:    Note:
 73:    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
 74:    for sparse matrices that already have locations it fills the locations with random numbers. It generates an error if used on sparse matrices that have
 75:    not been preallocated.

 77: .seealso: `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
 78: @*/
 79: PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
 80: {
 81:   PetscRandom randObj = NULL;

 86:   MatCheckPreallocated(x, 1);

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

100:   MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY);
101:   MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY);
102:   PetscRandomDestroy(&randObj);
103:   return 0;
104: }

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

109:    Logically Collective

111:    Input Parameter:
112: .  mat - the factored matrix

114:    Output Parameters:
115: +  pivot - the pivot value computed
116: -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
117:          the share the matrix

119:    Level: advanced

121:    Notes:
122:     This routine does not work for factorizations done with external packages.

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

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

128: .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
129:           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
130: @*/
131: PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
132: {
136:   *pivot = mat->factorerror_zeropivot_value;
137:   *row   = mat->factorerror_zeropivot_row;
138:   return 0;
139: }

141: /*@
142:    MatFactorGetError - gets the error code from a factorization

144:    Logically Collective

146:    Input Parameters:
147: .  mat - the factored matrix

149:    Output Parameter:
150: .  err  - the error code

152:    Level: advanced

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

157: .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
158:           `MatFactorError`
159: @*/
160: PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
161: {
164:   *err = mat->factorerrortype;
165:   return 0;
166: }

168: /*@
169:    MatFactorClearError - clears the error code in a factorization

171:    Logically Collective

173:    Input Parameter:
174: .  mat - the factored matrix

176:    Level: developer

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

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

193: PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
194: {
195:   Vec                r, l;
196:   const PetscScalar *al;
197:   PetscInt           i, nz, gnz, N, n;

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

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

250:   Input Parameter:
251: .    A  - the matrix

253:   Output Parameter:
254: .    keptrows - the rows that are not completely zero

256:   Level: intermediate

258:   Note:
259:     `keptrows` is set to `NULL` if all rows are nonzero.

261: .seealso: `Mat`, `MatFindZeroRows()`
262:  @*/
263: PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
264: {
270:   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
271:   else MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows);
272:   return 0;
273: }

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

278:   Input Parameter:
279: .    A  - the matrix

281:   Output Parameter:
282: .    zerorows - the rows that are completely zero

284:   Level: intermediate

286:   Note:
287:     `zerorows` is set to `NULL` if no rows are zero.

289: .seealso: `Mat`, `MatFindNonzeroRows()`
290:  @*/
291: PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
292: {
293:   IS       keptrows;
294:   PetscInt m, n;

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

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

316:    Not Collective

318:    Input Parameters:
319: .   A - the matrix

321:    Output Parameters:
322: .   a - the diagonal part (which is a SEQUENTIAL matrix)

324:    Level: advanced

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

329:    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.

331: .seealso: `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
332: @*/
333: PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
334: {
339:   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
340:   else {
341:     PetscMPIInt size;

343:     MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);
345:     *a = A;
346:   }
347:   return 0;
348: }

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

353:    Collective

355:    Input Parameters:
356: .  mat - the matrix

358:    Output Parameter:
359: .   trace - the sum of the diagonal entries

361:    Level: advanced

363: .seealso: `Mat`
364: @*/
365: PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
366: {
367:   Vec diag;

371:   MatCreateVecs(mat, &diag, NULL);
372:   MatGetDiagonal(mat, diag);
373:   VecSum(diag, trace);
374:   VecDestroy(&diag);
375:   return 0;
376: }

378: /*@
379:    MatRealPart - Zeros out the imaginary part of the matrix

381:    Logically Collective

383:    Input Parameters:
384: .  mat - the matrix

386:    Level: advanced

388: .seealso: `Mat`, `MatImaginaryPart()`
389: @*/
390: PetscErrorCode MatRealPart(Mat mat)
391: {
396:   MatCheckPreallocated(mat, 1);
397:   PetscUseTypeMethod(mat, realpart);
398:   return 0;
399: }

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

404:    Collective

406:    Input Parameter:
407: .  mat - the matrix

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

413:    Level: advanced

415:    Note:
416:    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`

418: .seealso: `Mat`, `VecCreateGhost()`
419: @*/
420: PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
421: {
426:   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
427:   else {
428:     if (nghosts) *nghosts = 0;
429:     if (ghosts) *ghosts = NULL;
430:   }
431:   return 0;
432: }

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

437:    Logically Collective

439:    Input Parameters:
440: .  mat - the matrix

442:    Level: advanced

444: .seealso: `Mat`, `MatRealPart()`
445: @*/
446: PetscErrorCode MatImaginaryPart(Mat mat)
447: {
452:   MatCheckPreallocated(mat, 1);
453:   PetscUseTypeMethod(mat, imaginarypart);
454:   return 0;
455: }

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

460:    Not Collective

462:    Input Parameter:
463: .  mat - the matrix

465:    Output Parameters:
466: +  missing - is any diagonal missing
467: -  dd - first diagonal entry that is missing (optional) on this process

469:    Level: advanced

471: .seealso: `Mat`
472: @*/
473: PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
474: {
480:   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
481:   return 0;
482: }

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

489:    Not Collective

491:    Input Parameters:
492: +  mat - the matrix
493: -  row - the row to get

495:    Output Parameters:
496: +  ncols -  if not `NULL`, the number of nonzeros in the row
497: .  cols - if not `NULL`, the column numbers
498: -  vals - if not `NULL`, the values

500:    Level: advanced

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

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

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

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

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

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

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

528:    Fortran Note:
529:    The calling sequence is
530: .vb
531:    MatGetRow(matrix,row,ncols,cols,values,ierr)
532:          Mat     matrix (input)
533:          integer row    (input)
534:          integer ncols  (output)
535:          integer cols(maxcols) (output)
536:          double precision (or double complex) values(maxcols) output
537: .ve
538:    where maxcols >= maximum nonzeros in any row of the matrix.

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

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

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

563: /*@
564:    MatConjugate - replaces the matrix values with their complex conjugates

566:    Logically Collective

568:    Input Parameters:
569: .  mat - the matrix

571:    Level: advanced

573: .seealso: `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
574: @*/
575: PetscErrorCode MatConjugate(Mat mat)
576: {
579:   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
580:     PetscUseTypeMethod(mat, conjugate);
581:     PetscObjectStateIncrease((PetscObject)mat);
582:   }
583:   return 0;
584: }

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

589:    Not Collective

591:    Input Parameters:
592: +  mat - the matrix
593: .  row - the row to get
594: .  ncols, cols - the number of nonzeros and their columns
595: -  vals - if nonzero the column values

597:    Level: advanced

599:    Notes:
600:    This routine should be called after you have finished examining the entries.

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

606:    Fortran Notes:
607:    The calling sequence is
608: .vb
609:    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
610:       Mat     matrix (input)
611:       integer row    (input)
612:       integer ncols  (output)
613:       integer cols(maxcols) (output)
614:       double precision (or double complex) values(maxcols) output
615: .ve
616:    Where maxcols >= maximum nonzeros in any row of the matrix.

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

621: .seealso: `Mat`, `MatGetRow()`
622: @*/
623: PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
624: {
628:   if (!mat->ops->restorerow) return 0;
629:   (*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
630:   if (ncols) *ncols = 0;
631:   if (cols) *cols = NULL;
632:   if (vals) *vals = NULL;
633:   return 0;
634: }

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

640:    Not Collective

642:    Input Parameters:
643: .  mat - the matrix

645:    Level: advanced

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

650: .seealso: `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
651: @*/
652: PetscErrorCode MatGetRowUpperTriangular(Mat mat)
653: {
658:   MatCheckPreallocated(mat, 1);
659:   if (!mat->ops->getrowuppertriangular) return 0;
660:   PetscUseTypeMethod(mat, getrowuppertriangular);
661:   return 0;
662: }

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

667:    Not Collective

669:    Input Parameters:
670: .  mat - the matrix

672:    Level: advanced

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

677: .seealso: `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
678: @*/
679: PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
680: {
685:   MatCheckPreallocated(mat, 1);
686:   if (!mat->ops->restorerowuppertriangular) return 0;
687:   PetscUseTypeMethod(mat, restorerowuppertriangular);
688:   return 0;
689: }

691: /*@C
692:    MatSetOptionsPrefix - Sets the prefix used for searching for all
693:    `Mat` options in the database.

695:    Logically Collective

697:    Input Parameters:
698: +  A - the matrix
699: -  prefix - the prefix to prepend to all option names

701:    Level: advanced

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

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

711: .seealso: `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
712: @*/
713: PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
714: {
716:   PetscObjectSetOptionsPrefix((PetscObject)A, prefix);
717:   return 0;
718: }

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

724:    Logically Collective

726:    Input Parameters:
727: +  A - the matrix
728: -  prefix - the prefix to prepend to all option names for the factored matrix

730:    Level: developer

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

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

739: .seealso: `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
740: @*/
741: PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
742: {
744:   if (prefix) {
747:     if (prefix != A->factorprefix) {
748:       PetscFree(A->factorprefix);
749:       PetscStrallocpy(prefix, &A->factorprefix);
750:     }
751:   } else PetscFree(A->factorprefix);
752:   return 0;
753: }

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

759:    Logically Collective

761:    Input Parameters:
762: +  A - the matrix
763: -  prefix - the prefix to prepend to all option names for the factored matrix

765:    Level: developer

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

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

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

784:   if (!prefix) return 0;
785:   if (!buf) {
786:     MatSetOptionsPrefixFactor(A, prefix);
787:     return 0;
788:   }

791:   PetscStrlen(prefix, &len1);
792:   PetscStrlen(buf, &len2);
793:   PetscMalloc1(1 + len1 + len2, &A->factorprefix);
794:   PetscStrcpy(A->factorprefix, buf);
795:   PetscStrcat(A->factorprefix, prefix);
796:   PetscFree(buf);
797:   return 0;
798: }

800: /*@C
801:    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
802:    matrix options in the database.

804:    Logically Collective

806:    Input Parameters:
807: +  A - the matrix
808: -  prefix - the prefix to prepend to all option names

810:    Level: advanced

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

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

825: /*@C
826:    MatGetOptionsPrefix - Gets the prefix used for searching for all
827:    matrix options in the database.

829:    Not Collective

831:    Input Parameter:
832: .  A - the matrix

834:    Output Parameter:
835: .  prefix - pointer to the prefix string used

837:    Level: advanced

839:    Fortran Note:
840:     On the fortran side, the user should pass in a string `prefix` of
841:    sufficient length to hold the prefix.

843: .seealso: `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
844: @*/
845: PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
846: {
849:   PetscObjectGetOptionsPrefix((PetscObject)A, prefix);
850:   return 0;
851: }

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

856:    Collective

858:    Input Parameters:
859: .  A - the matrix

861:    Level: beginner

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

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

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

870: .seealso: `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
871: @*/
872: PetscErrorCode MatResetPreallocation(Mat A)
873: {
876:   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
877:   return 0;
878: }

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

883:    Collective

885:    Input Parameters:
886: .  A - the matrix

888:    Level: intermediate

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

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

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

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

899: .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
900: @*/
901: PetscErrorCode MatSetUp(Mat A)
902: {
904:   if (!((PetscObject)A)->type_name) {
905:     PetscMPIInt size;

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

920: #if defined(PETSC_HAVE_SAWS)
921: #include <petscviewersaws.h>
922: #endif

924: /*@C
925:    MatViewFromOptions - View properties of the matrix from the options database

927:    Collective

929:    Input Parameters:
930: +  A - the matrix
931: .  obj - optional additional object that provides the options prefix to use
932: -  name - command line option

934:   Options Database Key:
935: .  -mat_view [viewertype]:... - the viewer and its options

937:    Level: intermediate

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

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

960: /*@C
961:    MatView - display information about a matrix in a variety ways

963:    Collective

965:    Input Parameters:
966: +  mat - the matrix
967: -  viewer - visualization context

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

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

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

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

1015:    Level: beginner

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

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

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

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

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

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

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

1053:   PetscViewerGetFormat(viewer, &format);
1054:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
1055:   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) return 0;

1057:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring);
1058:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
1059:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws);

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

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

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

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

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

1154:    Collective

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

1161:    Options Database Keys:
1162:    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1163:    block size
1164: .    -matload_block_size <bs> - set block size

1166:    Level: beginner

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

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

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

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

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

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

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

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

1217: $    PetscInt    MAT_FILE_CLASSID
1218: $    PetscInt    number of rows
1219: $    PetscInt    number of columns
1220: $    PetscInt    total number of nonzeros
1221: $    PetscInt    *number nonzeros in each row
1222: $    PetscInt    *column indices of all nonzeros (starting index is zero)
1223: $    PetscScalar *values of all nonzeros

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

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

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

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

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

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

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

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

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

1264: .seealso: `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1265:  @*/
1266: PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1267: {
1268:   PetscBool flg;


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

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

1285:   PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0);
1286:   PetscUseTypeMethod(mat, load, viewer);
1287:   PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0);
1288:   return 0;
1289: }

1291: static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1292: {
1293:   Mat_Redundant *redund = *redundant;

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

1311:     if (redund->subcomm) PetscCommDestroy(&redund->subcomm);
1312:     PetscFree(redund);
1313:   }
1314:   return 0;
1315: }

1317: /*@C
1318:    MatDestroy - Frees space taken by a matrix.

1320:    Collective

1322:    Input Parameter:
1323: .  A - the matrix

1325:    Level: beginner

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

1333: .seealso: `Mat`, `MatCreate()`
1334: @*/
1335: PetscErrorCode MatDestroy(Mat *A)
1336: {
1337:   if (!*A) return 0;
1339:   if (--((PetscObject)(*A))->refct > 0) {
1340:     *A = NULL;
1341:     return 0;
1342:   }

1344:   /* if memory was published with SAWs then destroy it */
1345:   PetscObjectSAWsViewOff((PetscObject)*A);
1346:   PetscTryTypeMethod((*A), destroy);

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

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

1372:    Not Collective

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

1381:    Level: beginner

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

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

1389:    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1390:    options cannot be mixed without intervening calls to the assembly
1391:    routines.

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

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

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

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

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

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

1425:   if (PetscDefined(USE_DEBUG)) {
1426:     PetscInt i, j;

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

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

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

1458:    Not Collective

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

1467:    Level: beginner

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

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

1475:    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1476:    options cannot be mixed without intervening calls to the assembly
1477:    routines.

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

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

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

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

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

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

1507:   ISGetIndices(ism, &rows);
1508:   ISGetIndices(isn, &cols);
1509:   ISGetLocalSize(ism, &m);
1510:   ISGetLocalSize(isn, &n);
1511:   MatSetValues(mat, m, rows, n, cols, v, addv);
1512:   ISRestoreIndices(ism, &rows);
1513:   ISRestoreIndices(isn, &cols);
1514:   return 0;
1515: }

1517: /*@
1518:    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1519:         values into a matrix

1521:    Not Collective

1523:    Input Parameters:
1524: +  mat - the matrix
1525: .  row - the (block) row to set
1526: -  v - a logically two-dimensional array of values

1528:    Level: intermediate

1530:    Notes:
1531:    The values, `v`, are column-oriented (for the block version) and sorted

1533:    All the nonzeros in the row must be provided

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

1537:    The row must belong to this process

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

1549:   ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow);
1550:   MatSetValuesRow(mat, globalrow, v);
1551:   return 0;
1552: }

1554: /*@
1555:    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1556:         values into a matrix

1558:    Not Collective

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

1565:    Level: advanced

1567:    Notes:
1568:    The values, `v`, are column-oriented for the block version.

1570:    All the nonzeros in the row must be provided

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

1574:    The row must belong to this process

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

1590:   if (mat->assembled) {
1591:     mat->was_assembled = PETSC_TRUE;
1592:     mat->assembled     = PETSC_FALSE;
1593:   }
1594:   PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1595:   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1596:   PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1597:   return 0;
1598: }

1600: /*@
1601:    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1602:      Using structured grid indexing

1604:    Not Collective

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

1615:    Level: beginner

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

1620:    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1621:    options cannot be mixed without intervening calls to the assembly
1622:    routines.

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

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

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

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

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

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

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

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

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

1655:    Fortran Note:
1656:    In Fortran idxm and idxn should be declared as
1657: $     MatStencil idxm(4,m),idxn(4,n)
1658:    and the values inserted using
1659: .vb
1660:     idxm(MatStencil_i,1) = i
1661:     idxm(MatStencil_j,1) = j
1662:     idxm(MatStencil_k,1) = k
1663:     idxm(MatStencil_c,1) = c
1664:     etc
1665: .ve

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

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

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

1715: /*@
1716:    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1717:      Using structured grid indexing

1719:    Not Collective

1721:    Input Parameters:
1722: +  mat - the matrix
1723: .  m - number of rows being entered
1724: .  idxm - grid coordinates for matrix rows being entered
1725: .  n - number of columns being entered
1726: .  idxn - grid coordinates for matrix columns being entered
1727: .  v - a logically two-dimensional array of values
1728: -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values

1730:    Level: beginner

1732:    Notes:
1733:    By default the values, `v`, are row-oriented and unsorted.
1734:    See `MatSetOption()` for other options.

1736:    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1737:    options cannot be mixed without intervening calls to the assembly
1738:    routines.

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

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

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

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

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

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

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

1764:    Fortran Note:
1765:    In Fortran idxm and idxn should be declared as
1766: $     MatStencil idxm(4,m),idxn(4,n)
1767:    and the values inserted using
1768: .vb
1769:     idxm(MatStencil_i,1) = i
1770:     idxm(MatStencil_j,1) = j
1771:     idxm(MatStencil_k,1) = k
1772:    etc
1773: .ve

1775: .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1776:           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1777:           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1778: @*/
1779: PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1780: {
1781:   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1782:   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1783:   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);

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

1792:   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1793:     jdxm = buf;
1794:     jdxn = buf + m;
1795:   } else {
1796:     PetscMalloc2(m, &bufm, n, &bufn);
1797:     jdxm = bufm;
1798:     jdxn = bufn;
1799:   }
1800:   for (i = 0; i < m; i++) {
1801:     for (j = 0; j < 3 - sdim; j++) dxm++;
1802:     tmp = *dxm++ - starts[0];
1803:     for (j = 0; j < sdim - 1; j++) {
1804:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1805:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1806:     }
1807:     dxm++;
1808:     jdxm[i] = tmp;
1809:   }
1810:   for (i = 0; i < n; i++) {
1811:     for (j = 0; j < 3 - sdim; j++) dxn++;
1812:     tmp = *dxn++ - starts[0];
1813:     for (j = 0; j < sdim - 1; j++) {
1814:       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1815:       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1816:     }
1817:     dxn++;
1818:     jdxn[i] = tmp;
1819:   }
1820:   MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv);
1821:   PetscFree2(bufm, bufn);
1822:   return 0;
1823: }

1825: /*@
1826:    MatSetStencil - Sets the grid information for setting values into a matrix via
1827:         `MatSetValuesStencil()`

1829:    Not Collective

1831:    Input Parameters:
1832: +  mat - the matrix
1833: .  dim - dimension of the grid 1, 2, or 3
1834: .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1835: .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1836: -  dof - number of degrees of freedom per node

1838:    Level: beginner

1840:    Notes:
1841:    Inspired by the structured grid interface to the HYPRE package
1842:    (www.llnl.gov/CASC/hyper)

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

1847: .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1848:           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1849: @*/
1850: PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1851: {

1856:   mat->stencil.dim = dim + (dof > 1);
1857:   for (PetscInt i = 0; i < dim; i++) {
1858:     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1859:     mat->stencil.starts[i] = starts[dim - i - 1];
1860:   }
1861:   mat->stencil.dims[dim]   = dof;
1862:   mat->stencil.starts[dim] = 0;
1863:   mat->stencil.noc         = (PetscBool)(dof == 1);
1864:   return 0;
1865: }

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

1870:    Not Collective

1872:    Input Parameters:
1873: +  mat - the matrix
1874: .  v - a logically two-dimensional array of values
1875: .  m  - the number of block rows
1876: .  idxm - the global block indices
1877: .  n - the number of block columns
1878: .  idxn - the global block indices
1879: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values

1881:    Level: intermediate

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

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

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

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

1899:    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1900:    options cannot be mixed without intervening calls to the assembly
1901:    routines.

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

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

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

1917:    Example:
1918: .vb
1919:    Suppose m=n=2 and block size(bs) = 2 The array is

1921:    1  2  | 3  4
1922:    5  6  | 7  8
1923:    - - - | - - -
1924:    9  10 | 11 12
1925:    13 14 | 15 16

1927:    v[] should be passed in like
1928:    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]

1930:   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1931:    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1932: .ve

1934: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1935: @*/
1936: PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1937: {
1941:   if (!m || !n) return 0; /* no values to insert */
1944:   MatCheckPreallocated(mat, 1);
1945:   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1947:   if (PetscDefined(USE_DEBUG)) {
1950:   }
1951:   if (PetscDefined(USE_DEBUG)) {
1952:     PetscInt rbs, cbs, M, N, i;
1953:     MatGetBlockSizes(mat, &rbs, &cbs);
1954:     MatGetSize(mat, &M, &N);
1957:   }
1958:   if (mat->assembled) {
1959:     mat->was_assembled = PETSC_TRUE;
1960:     mat->assembled     = PETSC_FALSE;
1961:   }
1962:   PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
1963:   if (mat->ops->setvaluesblocked) {
1964:     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1965:   } else {
1966:     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1967:     PetscInt i, j, bs, cbs;

1969:     MatGetBlockSizes(mat, &bs, &cbs);
1970:     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1971:       iidxm = buf;
1972:       iidxn = buf + m * bs;
1973:     } else {
1974:       PetscMalloc2(m * bs, &bufr, n * cbs, &bufc);
1975:       iidxm = bufr;
1976:       iidxn = bufc;
1977:     }
1978:     for (i = 0; i < m; i++) {
1979:       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
1980:     }
1981:     if (m != n || bs != cbs || idxm != idxn) {
1982:       for (i = 0; i < n; i++) {
1983:         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
1984:       }
1985:     } else iidxn = iidxm;
1986:     MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv);
1987:     PetscFree2(bufr, bufc);
1988:   }
1989:   PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
1990:   return 0;
1991: }

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

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

1998:    Input Parameters:
1999: +  mat - the matrix
2000: .  v - a logically two-dimensional array for storing the values
2001: .  m  - the number of rows
2002: .  idxm - the  global indices of the rows
2003: .  n - the number of columns
2004: -  idxn - the global indices of the columns

2006:    Level: advanced

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

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

2016:      `MatGetValues()` requires that the matrix has been assembled
2017:      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2018:      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2019:      without intermediate matrix assembly.

2021:      Negative row or column indices will be ignored and those locations in `v` will be
2022:      left unchanged.

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

2028: .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2029: @*/
2030: PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2031: {
2034:   if (!m || !n) return 0;
2040:   MatCheckPreallocated(mat, 1);

2042:   PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2043:   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2044:   PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2045:   return 0;
2046: }

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

2052:    Not Collective

2054:    Input Parameters:
2055: +  mat - the matrix
2056: .  nrow - number of rows
2057: .  irow - the row local indices
2058: .  ncol - number of columns
2059: -  icol - the column local indices

2061:    Output Parameter:
2062: .  y -  a logically two-dimensional array of values

2064:    Level: advanced

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

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

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

2078: .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2079:           `MatSetValuesLocal()`, `MatGetValues()`
2080: @*/
2081: PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2082: {
2086:   MatCheckPreallocated(mat, 1);
2087:   if (!nrow || !ncol) return 0; /* no values to retrieve */
2090:   if (PetscDefined(USE_DEBUG)) {
2093:   }
2095:   PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2096:   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2097:   else {
2098:     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2099:     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2100:       irowm = buf;
2101:       icolm = buf + nrow;
2102:     } else {
2103:       PetscMalloc2(nrow, &bufr, ncol, &bufc);
2104:       irowm = bufr;
2105:       icolm = bufc;
2106:     }
2109:     ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm);
2110:     ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm);
2111:     MatGetValues(mat, nrow, irowm, ncol, icolm, y);
2112:     PetscFree2(bufr, bufc);
2113:   }
2114:   PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2115:   return 0;
2116: }

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

2122:   Not Collective

2124:   Input Parameters:
2125: + mat - the matrix
2126: . nb - the number of blocks
2127: . bs - the number of rows (and columns) in each block
2128: . rows - a concatenation of the rows for each block
2129: - v - a concatenation of logically two-dimensional arrays of values

2131:   Level: advanced

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

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

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

2149:   PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0);
2150:   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2151:   else {
2152:     for (PetscInt b = 0; b < nb; ++b) MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES);
2153:   }
2154:   PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0);
2155:   return 0;
2156: }

2158: /*@
2159:    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2160:    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2161:    using a local (per-processor) numbering.

2163:    Not Collective

2165:    Input Parameters:
2166: +  x - the matrix
2167: .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2168: -  cmapping - column mapping

2170:    Level: intermediate

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

2175: .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2176: @*/
2177: PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2178: {
2183:   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2184:   else {
2185:     PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping);
2186:     PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping);
2187:   }
2188:   return 0;
2189: }

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

2194:    Not Collective

2196:    Input Parameter:
2197: .  A - the matrix

2199:    Output Parameters:
2200: + rmapping - row mapping
2201: - cmapping - column mapping

2203:    Level: advanced

2205: .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2206: @*/
2207: PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2208: {
2211:   if (rmapping) {
2213:     *rmapping = A->rmap->mapping;
2214:   }
2215:   if (cmapping) {
2217:     *cmapping = A->cmap->mapping;
2218:   }
2219:   return 0;
2220: }

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

2225:    Logically Collective

2227:    Input Parameters:
2228: +  A - the matrix
2229: . rmap - row layout
2230: - cmap - column layout

2232:    Level: advanced

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

2237: .seealso: `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2238: @*/
2239: PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2240: {
2242:   PetscLayoutReference(rmap, &A->rmap);
2243:   PetscLayoutReference(cmap, &A->cmap);
2244:   return 0;
2245: }

2247: /*@
2248:    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns

2250:    Not Collective

2252:    Input Parameter:
2253: .  A - the matrix

2255:    Output Parameters:
2256: + rmap - row layout
2257: - cmap - column layout

2259:    Level: advanced

2261: .seealso: `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2262: @*/
2263: PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2264: {
2267:   if (rmap) {
2269:     *rmap = A->rmap;
2270:   }
2271:   if (cmap) {
2273:     *cmap = A->cmap;
2274:   }
2275:   return 0;
2276: }

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

2282:    Not Collective

2284:    Input Parameters:
2285: +  mat - the matrix
2286: .  nrow - number of rows
2287: .  irow - the row local indices
2288: .  ncol - number of columns
2289: .  icol - the column local indices
2290: .  y -  a logically two-dimensional array of values
2291: -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

2293:    Level: intermediate

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

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

2301:    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2302:    options cannot be mixed without intervening calls to the assembly
2303:    routines.

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

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

2312: .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2313:           `MatGetValuesLocal()`
2314: @*/
2315: PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2316: {
2320:   MatCheckPreallocated(mat, 1);
2321:   if (!nrow || !ncol) return 0; /* no values to insert */
2324:   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2326:   if (PetscDefined(USE_DEBUG)) {
2329:   }

2331:   if (mat->assembled) {
2332:     mat->was_assembled = PETSC_TRUE;
2333:     mat->assembled     = PETSC_FALSE;
2334:   }
2335:   PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2336:   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2337:   else {
2338:     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2339:     const PetscInt *irowm, *icolm;

2341:     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2342:       bufr  = buf;
2343:       bufc  = buf + nrow;
2344:       irowm = bufr;
2345:       icolm = bufc;
2346:     } else {
2347:       PetscMalloc2(nrow, &bufr, ncol, &bufc);
2348:       irowm = bufr;
2349:       icolm = bufc;
2350:     }
2351:     if (mat->rmap->mapping) ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr);
2352:     else irowm = irow;
2353:     if (mat->cmap->mapping) {
2354:       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2355:         ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc);
2356:       } else icolm = irowm;
2357:     } else icolm = icol;
2358:     MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv);
2359:     if (bufr != buf) PetscFree2(bufr, bufc);
2360:   }
2361:   PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2362:   return 0;
2363: }

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

2369:    Not Collective

2371:    Input Parameters:
2372: +  x - the matrix
2373: .  nrow - number of rows
2374: .  irow - the row local indices
2375: .  ncol - number of columns
2376: .  icol - the column local indices
2377: .  y -  a logically two-dimensional array of values
2378: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

2380:    Level: intermediate

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

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

2389:    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2390:    options cannot be mixed without intervening calls to the assembly
2391:    routines.

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

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

2400: .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2401:           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2402: @*/
2403: PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2404: {
2408:   MatCheckPreallocated(mat, 1);
2409:   if (!nrow || !ncol) return 0; /* no values to insert */
2412:   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2414:   if (PetscDefined(USE_DEBUG)) {
2417:   }

2419:   if (mat->assembled) {
2420:     mat->was_assembled = PETSC_TRUE;
2421:     mat->assembled     = PETSC_FALSE;
2422:   }
2423:   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2424:     PetscInt irbs, rbs;
2425:     MatGetBlockSizes(mat, &rbs, NULL);
2426:     ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs);
2428:   }
2429:   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2430:     PetscInt icbs, cbs;
2431:     MatGetBlockSizes(mat, NULL, &cbs);
2432:     ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs);
2434:   }
2435:   PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0);
2436:   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2437:   else {
2438:     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2439:     const PetscInt *irowm, *icolm;

2441:     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2442:       bufr  = buf;
2443:       bufc  = buf + nrow;
2444:       irowm = bufr;
2445:       icolm = bufc;
2446:     } else {
2447:       PetscMalloc2(nrow, &bufr, ncol, &bufc);
2448:       irowm = bufr;
2449:       icolm = bufc;
2450:     }
2451:     if (mat->rmap->mapping) ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr);
2452:     else irowm = irow;
2453:     if (mat->cmap->mapping) {
2454:       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2455:         ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc);
2456:       } else icolm = irowm;
2457:     } else icolm = icol;
2458:     MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv);
2459:     if (bufr != buf) PetscFree2(bufr, bufc);
2460:   }
2461:   PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0);
2462:   return 0;
2463: }

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

2468:    Collective

2470:    Input Parameters:
2471: +  mat - the matrix
2472: -  x   - the vector to be multiplied

2474:    Output Parameters:
2475: .  y - the result

2477:    Level: developer

2479:    Note:
2480:    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2481:    call `MatMultDiagonalBlock`(A,y,y).

2483: .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2484: @*/
2485: PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2486: {

2495:   MatCheckPreallocated(mat, 1);

2497:   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2498:   PetscObjectStateIncrease((PetscObject)y);
2499:   return 0;
2500: }

2502: /*@
2503:    MatMult - Computes the matrix-vector product, y = Ax.

2505:    Neighbor-wise Collective

2507:    Input Parameters:
2508: +  mat - the matrix
2509: -  x   - the vector to be multiplied

2511:    Output Parameters:
2512: .  y - the result

2514:    Level: beginner

2516:    Note:
2517:    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2518:    call `MatMult`(A,y,y).

2520: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2521: @*/
2522: PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2523: {
2535:   VecSetErrorIfLocked(y, 3);
2536:   if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2537:   MatCheckPreallocated(mat, 1);

2539:   VecLockReadPush(x);
2540:   PetscLogEventBegin(MAT_Mult, mat, x, y, 0);
2541:   PetscUseTypeMethod(mat, mult, x, y);
2542:   PetscLogEventEnd(MAT_Mult, mat, x, y, 0);
2543:   if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2544:   VecLockReadPop(x);
2545:   return 0;
2546: }

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

2551:    Neighbor-wise Collective

2553:    Input Parameters:
2554: +  mat - the matrix
2555: -  x   - the vector to be multiplied

2557:    Output Parameters:
2558: .  y - the result

2560:    Level: beginner

2562:    Notes:
2563:    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2564:    call `MatMultTranspose`(A,y,y).

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

2569: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2570: @*/
2571: PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2572: {
2573:   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;


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

2590:   if (!mat->ops->multtranspose) {
2591:     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2593:   } else op = mat->ops->multtranspose;
2594:   PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0);
2595:   VecLockReadPush(x);
2596:   (*op)(mat, x, y);
2597:   VecLockReadPop(x);
2598:   PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0);
2599:   PetscObjectStateIncrease((PetscObject)y);
2600:   if (mat->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
2601:   return 0;
2602: }

2604: /*@
2605:    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.

2607:    Neighbor-wise Collective

2609:    Input Parameters:
2610: +  mat - the matrix
2611: -  x   - the vector to be multilplied

2613:    Output Parameters:
2614: .  y - the result

2616:    Level: beginner

2618:    Notes:
2619:    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2620:    call `MatMultHermitianTranspose`(A,y,y).

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

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

2626: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2627: @*/
2628: PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2629: {

2642:   MatCheckPreallocated(mat, 1);

2644:   PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0);
2645: #if defined(PETSC_USE_COMPLEX)
2646:   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2647:     VecLockReadPush(x);
2648:     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2649:     else PetscUseTypeMethod(mat, mult, x, y);
2650:     VecLockReadPop(x);
2651:   } else {
2652:     Vec w;
2653:     VecDuplicate(x, &w);
2654:     VecCopy(x, w);
2655:     VecConjugate(w);
2656:     MatMultTranspose(mat, w, y);
2657:     VecDestroy(&w);
2658:     VecConjugate(y);
2659:   }
2660:   PetscObjectStateIncrease((PetscObject)y);
2661: #else
2662:   MatMultTranspose(mat, x, y);
2663: #endif
2664:   PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0);
2665:   return 0;
2666: }

2668: /*@
2669:     MatMultAdd -  Computes v3 = v2 + A * v1.

2671:     Neighbor-wise Collective

2673:     Input Parameters:
2674: +   mat - the matrix
2675: -   v1, v2 - the vectors

2677:     Output Parameters:
2678: .   v3 - the result

2680:     Level: beginner

2682:     Note:
2683:     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2684:     call `MatMultAdd`(A,v1,v2,v1).

2686: .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2687: @*/
2688: PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2689: {

2704:   MatCheckPreallocated(mat, 1);

2706:   PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3);
2707:   VecLockReadPush(v1);
2708:   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2709:   VecLockReadPop(v1);
2710:   PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3);
2711:   PetscObjectStateIncrease((PetscObject)v3);
2712:   return 0;
2713: }

2715: /*@
2716:    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.

2718:    Neighbor-wise Collective

2720:    Input Parameters:
2721: +  mat - the matrix
2722: -  v1, v2 - the vectors

2724:    Output Parameters:
2725: .  v3 - the result

2727:    Level: beginner

2729:    Note:
2730:    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2731:    call `MatMultTransposeAdd`(A,v1,v2,v1).

2733: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2734: @*/
2735: PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2736: {
2737:   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;


2752:   MatCheckPreallocated(mat, 1);

2754:   PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3);
2755:   VecLockReadPush(v1);
2756:   (*op)(mat, v1, v2, v3);
2757:   VecLockReadPop(v1);
2758:   PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3);
2759:   PetscObjectStateIncrease((PetscObject)v3);
2760:   return 0;
2761: }

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

2766:    Neighbor-wise Collective

2768:    Input Parameters:
2769: +  mat - the matrix
2770: -  v1, v2 - the vectors

2772:    Output Parameters:
2773: .  v3 - the result

2775:    Level: beginner

2777:    Note:
2778:    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2779:    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).

2781: .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2782: @*/
2783: PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2784: {

2797:   MatCheckPreallocated(mat, 1);

2799:   PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2800:   VecLockReadPush(v1);
2801:   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2802:   else {
2803:     Vec w, z;
2804:     VecDuplicate(v1, &w);
2805:     VecCopy(v1, w);
2806:     VecConjugate(w);
2807:     VecDuplicate(v3, &z);
2808:     MatMultTranspose(mat, w, z);
2809:     VecDestroy(&w);
2810:     VecConjugate(z);
2811:     if (v2 != v3) {
2812:       VecWAXPY(v3, 1.0, v2, z);
2813:     } else {
2814:       VecAXPY(v3, 1.0, z);
2815:     }
2816:     VecDestroy(&z);
2817:   }
2818:   VecLockReadPop(v1);
2819:   PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3);
2820:   PetscObjectStateIncrease((PetscObject)v3);
2821:   return 0;
2822: }

2824: /*@C
2825:    MatGetFactorType - gets the type of factorization it is

2827:    Not Collective

2829:    Input Parameters:
2830: .  mat - the matrix

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

2835:    Level: intermediate

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

2849: /*@C
2850:    MatSetFactorType - sets the type of factorization it is

2852:    Logically Collective

2854:    Input Parameters:
2855: +  mat - the matrix
2856: -  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`

2858:    Level: intermediate

2860: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2861:           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2862: @*/
2863: PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2864: {
2867:   mat->factortype = t;
2868:   return 0;
2869: }

2871: /*@C
2872:    MatGetInfo - Returns information about matrix storage (number of
2873:    nonzeros, memory, etc.).

2875:    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag

2877:    Input Parameters:
2878: +  mat - the matrix
2879: -  flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors)

2881:    Output Parameters:
2882: .  info - matrix information context

2884:    Notes:
2885:    The `MatInfo` context contains a variety of matrix data, including
2886:    number of nonzeros allocated and used, number of mallocs during
2887:    matrix assembly, etc.  Additional information for factored matrices
2888:    is provided (such as the fill ratio, number of mallocs during
2889:    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2890:    when using the runtime options
2891: $       -info -mat_view ::ascii_info

2893:    Example for C/C++ Users:
2894:    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2895:    data within the MatInfo context.  For example,
2896: .vb
2897:       MatInfo info;
2898:       Mat     A;
2899:       double  mal, nz_a, nz_u;

2901:       MatGetInfo(A,MAT_LOCAL,&info);
2902:       mal  = info.mallocs;
2903:       nz_a = info.nz_allocated;
2904: .ve

2906:    Example for Fortran Users:
2907:    Fortran users should declare info as a double precision
2908:    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2909:    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2910:    a complete list of parameter names.
2911: .vb
2912:       double  precision info(MAT_INFO_SIZE)
2913:       double  precision mal, nz_a
2914:       Mat     A
2915:       integer ierr

2917:       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2918:       mal = info(MAT_INFO_MALLOCS)
2919:       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2920: .ve

2922:     Level: intermediate

2924:     Developer Note:
2925:     Fortran interface is not autogenerated as the
2926:     interface definition cannot be generated correctly [due to MatInfo]

2928: .seealso: `Mat`, `MatInfo`, `MatStashGetInfo()`
2929: @*/
2930: PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2931: {
2935:   MatCheckPreallocated(mat, 1);
2936:   PetscUseTypeMethod(mat, getinfo, flag, info);
2937:   return 0;
2938: }

2940: /*
2941:    This is used by external packages where it is not easy to get the info from the actual
2942:    matrix factorization.
2943: */
2944: PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2945: {
2946:   PetscMemzero(info, sizeof(MatInfo));
2947:   return 0;
2948: }

2950: /*@C
2951:    MatLUFactor - Performs in-place LU factorization of matrix.

2953:    Collective

2955:    Input Parameters:
2956: +  mat - the matrix
2957: .  row - row permutation
2958: .  col - column permutation
2959: -  info - options for factorization, includes
2960: .vb
2961:           fill - expected fill as ratio of original fill.
2962:           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2963:                    Run with the option -info to determine an optimal value to use
2964: .ve
2965:    Level: developer

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

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

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

2978:    Developer Note:
2979:    The Fortran interface is not autogenerated as the
2980:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

2982: .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2983:           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2984: @*/
2985: PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
2986: {
2987:   MatFactorInfo tinfo;

2996:   MatCheckPreallocated(mat, 1);
2997:   if (!info) {
2998:     MatFactorInfoInitialize(&tinfo);
2999:     info = &tinfo;
3000:   }

3002:   PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0);
3003:   PetscUseTypeMethod(mat, lufactor, row, col, info);
3004:   PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0);
3005:   PetscObjectStateIncrease((PetscObject)mat);
3006:   return 0;
3007: }

3009: /*@C
3010:    MatILUFactor - Performs in-place ILU factorization of matrix.

3012:    Collective

3014:    Input Parameters:
3015: +  mat - the matrix
3016: .  row - row permutation
3017: .  col - column permutation
3018: -  info - structure containing
3019: .vb
3020:       levels - number of levels of fill.
3021:       expected fill - as ratio of original fill.
3022:       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3023:                 missing diagonal entries)
3024: .ve

3026:    Level: developer

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

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

3037:    Developer Note:
3038:    The Fortran interface is not autogenerated as the
3039:    interface definition cannot be generated correctly [due to MatFactorInfo]

3041: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3042: @*/
3043: PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3044: {
3053:   MatCheckPreallocated(mat, 1);

3055:   PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0);
3056:   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3057:   PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0);
3058:   PetscObjectStateIncrease((PetscObject)mat);
3059:   return 0;
3060: }

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

3066:    Collective on fact

3068:    Input Parameters:
3069: +  fact - the factor matrix obtained with `MatGetFactor()`
3070: .  mat - the matrix
3071: .  row, col - row and column permutations
3072: -  info - options for factorization, includes
3073: .vb
3074:           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3075:           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3076: .ve

3078:    Level: developer

3080:    Notes:
3081:     See [Matrix Factorization](sec_matfactor) for additional information about factorizations

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

3087:    Developer Note:
3088:    The Fortran interface is not autogenerated as the
3089:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3091: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3092: @*/
3093: PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3094: {
3095:   MatFactorInfo tinfo;

3105:   if (!(fact)->ops->lufactorsymbolic) {
3106:     MatSolverType stype;
3107:     MatFactorGetSolverType(fact, &stype);
3108:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3109:   }
3110:   MatCheckPreallocated(mat, 2);
3111:   if (!info) {
3112:     MatFactorInfoInitialize(&tinfo);
3113:     info = &tinfo;
3114:   }

3116:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0);
3117:   (fact->ops->lufactorsymbolic)(fact, mat, row, col, info);
3118:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0);
3119:   PetscObjectStateIncrease((PetscObject)fact);
3120:   return 0;
3121: }

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

3127:    Collective on fact

3129:    Input Parameters:
3130: +  fact - the factor matrix obtained with `MatGetFactor()`
3131: .  mat - the matrix
3132: -  info - options for factorization

3134:    Level: developer

3136:    Notes:
3137:    See `MatLUFactor()` for in-place factorization.  See
3138:    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.

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

3144:     Developer Note:
3145:     The Fortran interface is not autogenerated as the
3146:     interface definition cannot be generated correctly [due to `MatFactorInfo`]

3148: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3149: @*/
3150: PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3151: {
3152:   MatFactorInfo tinfo;

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

3163:   MatCheckPreallocated(mat, 2);
3164:   if (!info) {
3165:     MatFactorInfoInitialize(&tinfo);
3166:     info = &tinfo;
3167:   }

3169:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0);
3170:   else PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0);
3171:   (fact->ops->lufactornumeric)(fact, mat, info);
3172:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0);
3173:   else PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0);
3174:   MatViewFromOptions(fact, NULL, "-mat_factor_view");
3175:   PetscObjectStateIncrease((PetscObject)fact);
3176:   return 0;
3177: }

3179: /*@C
3180:    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3181:    symmetric matrix.

3183:    Collective

3185:    Input Parameters:
3186: +  mat - the matrix
3187: .  perm - row and column permutations
3188: -  f - expected fill as ratio of original fill

3190:    Level: developer

3192:    Notes:
3193:    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3194:    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.

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

3200:    Developer Note:
3201:    The Fortran interface is not autogenerated as the
3202:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3204: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3205:           `MatGetOrdering()`
3206: @*/
3207: PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3208: {
3209:   MatFactorInfo tinfo;

3218:   MatCheckPreallocated(mat, 1);
3219:   if (!info) {
3220:     MatFactorInfoInitialize(&tinfo);
3221:     info = &tinfo;
3222:   }

3224:   PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0);
3225:   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3226:   PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0);
3227:   PetscObjectStateIncrease((PetscObject)mat);
3228:   return 0;
3229: }

3231: /*@C
3232:    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3233:    of a symmetric matrix.

3235:    Collective on fact

3237:    Input Parameters:
3238: +  fact - the factor matrix obtained with `MatGetFactor()`
3239: .  mat - the matrix
3240: .  perm - row and column permutations
3241: -  info - options for factorization, includes
3242: .vb
3243:           fill - expected fill as ratio of original fill.
3244:           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3245:                    Run with the option -info to determine an optimal value to use
3246: .ve

3248:    Level: developer

3250:    Notes:
3251:    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3252:    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.

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

3258:    Developer Note:
3259:    The Fortran interface is not autogenerated as the
3260:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3262: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3263:           `MatGetOrdering()`
3264: @*/
3265: PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3266: {
3267:   MatFactorInfo tinfo;

3277:   if (!(fact)->ops->choleskyfactorsymbolic) {
3278:     MatSolverType stype;
3279:     MatFactorGetSolverType(fact, &stype);
3280:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3281:   }
3282:   MatCheckPreallocated(mat, 2);
3283:   if (!info) {
3284:     MatFactorInfoInitialize(&tinfo);
3285:     info = &tinfo;
3286:   }

3288:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3289:   (fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info);
3290:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0);
3291:   PetscObjectStateIncrease((PetscObject)fact);
3292:   return 0;
3293: }

3295: /*@C
3296:    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3297:    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3298:    `MatCholeskyFactorSymbolic()`.

3300:    Collective on fact

3302:    Input Parameters:
3303: +  fact - the factor matrix obtained with `MatGetFactor()`
3304: .  mat - the initial matrix
3305: .  info - options for factorization
3306: -  fact - the symbolic factor of mat

3308:    Level: developer

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

3315:    Developer Note:
3316:    The Fortran interface is not autogenerated as the
3317:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3319: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3320: @*/
3321: PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3322: {
3323:   MatFactorInfo tinfo;

3332:              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3333:   MatCheckPreallocated(mat, 2);
3334:   if (!info) {
3335:     MatFactorInfoInitialize(&tinfo);
3336:     info = &tinfo;
3337:   }

3339:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3340:   else PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0);
3341:   (fact->ops->choleskyfactornumeric)(fact, mat, info);
3342:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0);
3343:   else PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0);
3344:   MatViewFromOptions(fact, NULL, "-mat_factor_view");
3345:   PetscObjectStateIncrease((PetscObject)fact);
3346:   return 0;
3347: }

3349: /*@
3350:    MatQRFactor - Performs in-place QR factorization of matrix.

3352:    Collective

3354:    Input Parameters:
3355: +  mat - the matrix
3356: .  col - column permutation
3357: -  info - options for factorization, includes
3358: .vb
3359:           fill - expected fill as ratio of original fill.
3360:           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3361:                    Run with the option -info to determine an optimal value to use
3362: .ve

3364:    Level: developer

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

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

3374:    Developer Note:
3375:    The Fortran interface is not autogenerated as the
3376:    interface definition cannot be generated correctly [due to MatFactorInfo]

3378: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3379:           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3380: @*/
3381: PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3382: {
3389:   MatCheckPreallocated(mat, 1);
3390:   PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0);
3391:   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3392:   PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0);
3393:   PetscObjectStateIncrease((PetscObject)mat);
3394:   return 0;
3395: }

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

3401:    Collective on fact

3403:    Input Parameters:
3404: +  fact - the factor matrix obtained with `MatGetFactor()`
3405: .  mat - the matrix
3406: .  col - column permutation
3407: -  info - options for factorization, includes
3408: .vb
3409:           fill - expected fill as ratio of original fill.
3410:           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3411:                    Run with the option -info to determine an optimal value to use
3412: .ve

3414:    Level: developer

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

3421:    Developer Note:
3422:    The Fortran interface is not autogenerated as the
3423:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3425: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3426: @*/
3427: PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3428: {
3429:   MatFactorInfo tinfo;

3438:   MatCheckPreallocated(mat, 2);
3439:   if (!info) {
3440:     MatFactorInfoInitialize(&tinfo);
3441:     info = &tinfo;
3442:   }

3444:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0);
3445:   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3446:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0);
3447:   PetscObjectStateIncrease((PetscObject)fact);
3448:   return 0;
3449: }

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

3455:    Collective on fact

3457:    Input Parameters:
3458: +  fact - the factor matrix obtained with `MatGetFactor()`
3459: .  mat - the matrix
3460: -  info - options for factorization

3462:    Level: developer

3464:    Notes:
3465:    See `MatQRFactor()` for in-place factorization.

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

3471:    Developer Note:
3472:    The Fortran interface is not autogenerated as the
3473:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3475: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3476: @*/
3477: PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3478: {
3479:   MatFactorInfo tinfo;

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

3489:   MatCheckPreallocated(mat, 2);
3490:   if (!info) {
3491:     MatFactorInfoInitialize(&tinfo);
3492:     info = &tinfo;
3493:   }

3495:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0);
3496:   else PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0);
3497:   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3498:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0);
3499:   else PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0);
3500:   MatViewFromOptions(fact, NULL, "-mat_factor_view");
3501:   PetscObjectStateIncrease((PetscObject)fact);
3502:   return 0;
3503: }

3505: /*@
3506:    MatSolve - Solves A x = b, given a factored matrix.

3508:    Neighbor-wise Collective

3510:    Input Parameters:
3511: +  mat - the factored matrix
3512: -  b - the right-hand-side vector

3514:    Output Parameter:
3515: .  x - the result vector

3517:    Level: developer

3519:    Notes:
3520:    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3521:    call `MatSolve`(A,x,x).

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

3527: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3528: @*/
3529: PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3530: {
3541:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3542:   MatCheckPreallocated(mat, 1);

3544:   PetscLogEventBegin(MAT_Solve, mat, b, x, 0);
3545:   if (mat->factorerrortype) {
3546:     PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3547:     VecSetInf(x);
3548:   } else PetscUseTypeMethod(mat, solve, b, x);
3549:   PetscLogEventEnd(MAT_Solve, mat, b, x, 0);
3550:   PetscObjectStateIncrease((PetscObject)x);
3551:   return 0;
3552: }

3554: static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3555: {
3556:   Vec      b, x;
3557:   PetscInt N, i;
3558:   PetscErrorCode (*f)(Mat, Vec, Vec);
3559:   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;

3561:   if (A->factorerrortype) {
3562:     PetscInfo(A, "MatFactorError %d\n", A->factorerrortype);
3563:     MatSetInf(X);
3564:     return 0;
3565:   }
3566:   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3568:   MatBoundToCPU(A, &Abound);
3569:   if (!Abound) {
3570:     PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "");
3571:     PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "");
3572:   }
3573: #if defined(PETSC_HAVE_CUDA)
3574:   if (Bneedconv) MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B);
3575:   if (Xneedconv) MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X);
3576: #elif (PETSC_HAVE_HIP)
3577:   if (Bneedconv) MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B);
3578:   if (Xneedconv) MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X);
3579: #endif
3580:   MatGetSize(B, NULL, &N);
3581:   for (i = 0; i < N; i++) {
3582:     MatDenseGetColumnVecRead(B, i, &b);
3583:     MatDenseGetColumnVecWrite(X, i, &x);
3584:     (*f)(A, b, x);
3585:     MatDenseRestoreColumnVecWrite(X, i, &x);
3586:     MatDenseRestoreColumnVecRead(B, i, &b);
3587:   }
3588:   if (Bneedconv) MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B);
3589:   if (Xneedconv) MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X);
3590:   return 0;
3591: }

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

3596:    Neighbor-wise Collective

3598:    Input Parameters:
3599: +  A - the factored matrix
3600: -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)

3602:    Output Parameter:
3603: .  X - the result matrix (dense matrix)

3605:    Level: developer

3607:    Note:
3608:    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3609:    otherwise, `B` and `X` cannot be the same.

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

3628:   PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3629:   if (!A->ops->matsolve) {
3630:     PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name);
3631:     MatMatSolve_Basic(A, B, X, PETSC_FALSE);
3632:   } else PetscUseTypeMethod(A, matsolve, B, X);
3633:   PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3634:   PetscObjectStateIncrease((PetscObject)X);
3635:   return 0;
3636: }

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

3641:    Neighbor-wise Collective

3643:    Input Parameters:
3644: +  A - the factored matrix
3645: -  B - the right-hand-side matrix  (`MATDENSE` matrix)

3647:    Output Parameter:
3648: .  X - the result matrix (dense matrix)

3650:    Level: developer

3652:    Note:
3653:    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3654:    call `MatMatSolveTranspose`(A,X,X).

3656: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3657: @*/
3658: PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3659: {
3671:   if (!A->rmap->N && !A->cmap->N) return 0;
3673:   MatCheckPreallocated(A, 1);

3675:   PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3676:   if (!A->ops->matsolvetranspose) {
3677:     PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name);
3678:     MatMatSolve_Basic(A, B, X, PETSC_TRUE);
3679:   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3680:   PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3681:   PetscObjectStateIncrease((PetscObject)X);
3682:   return 0;
3683: }

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

3688:    Neighbor-wise Collective

3690:    Input Parameters:
3691: +  A - the factored matrix
3692: -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`

3694:    Output Parameter:
3695: .  X - the result matrix (dense matrix)

3697:    Level: developer

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

3703: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3704: @*/
3705: PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3706: {

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

3722:   PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0);
3723:   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3724:   PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0);
3725:   PetscObjectStateIncrease((PetscObject)X);
3726:   return 0;
3727: }

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

3733:    Neighbor-wise Collective

3735:    Input Parameters:
3736: +  mat - the factored matrix
3737: -  b - the right-hand-side vector

3739:    Output Parameter:
3740: .  x - the result vector

3742:    Level: developer

3744:    Notes:
3745:    `MatSolve()` should be used for most applications, as it performs
3746:    a forward solve followed by a backward solve.

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

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

3757: .seealso: `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3758: @*/
3759: PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3760: {
3771:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3772:   MatCheckPreallocated(mat, 1);

3774:   PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0);
3775:   PetscUseTypeMethod(mat, forwardsolve, b, x);
3776:   PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0);
3777:   PetscObjectStateIncrease((PetscObject)x);
3778:   return 0;
3779: }

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

3785:    Neighbor-wise Collective

3787:    Input Parameters:
3788: +  mat - the factored matrix
3789: -  b - the right-hand-side vector

3791:    Output Parameter:
3792: .  x - the result vector

3794:    Level: developer

3796:    Notes:
3797:    `MatSolve()` should be used for most applications, as it performs
3798:    a forward solve followed by a backward solve.

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

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

3809: .seealso: `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3810: @*/
3811: PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3812: {
3823:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3824:   MatCheckPreallocated(mat, 1);

3826:   PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0);
3827:   PetscUseTypeMethod(mat, backwardsolve, b, x);
3828:   PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0);
3829:   PetscObjectStateIncrease((PetscObject)x);
3830:   return 0;
3831: }

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

3836:    Neighbor-wise Collective

3838:    Input Parameters:
3839: +  mat - the factored matrix
3840: .  b - the right-hand-side vector
3841: -  y - the vector to be added to

3843:    Output Parameter:
3844: .  x - the result vector

3846:    Level: developer

3848:    Note:
3849:    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3850:    call `MatSolveAdd`(A,x,y,x).

3852: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3853: @*/
3854: PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3855: {
3856:   PetscScalar one = 1.0;
3857:   Vec         tmp;

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

3876:   PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y);
3877:   if (mat->factorerrortype) {
3878:     PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3879:     VecSetInf(x);
3880:   } else if (mat->ops->solveadd) {
3881:     PetscUseTypeMethod(mat, solveadd, b, y, x);
3882:   } else {
3883:     /* do the solve then the add manually */
3884:     if (x != y) {
3885:       MatSolve(mat, b, x);
3886:       VecAXPY(x, one, y);
3887:     } else {
3888:       VecDuplicate(x, &tmp);
3889:       VecCopy(x, tmp);
3890:       MatSolve(mat, b, x);
3891:       VecAXPY(x, one, tmp);
3892:       VecDestroy(&tmp);
3893:     }
3894:   }
3895:   PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y);
3896:   PetscObjectStateIncrease((PetscObject)x);
3897:   return 0;
3898: }

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

3903:    Neighbor-wise Collective

3905:    Input Parameters:
3906: +  mat - the factored matrix
3907: -  b - the right-hand-side vector

3909:    Output Parameter:
3910: .  x - the result vector

3912:    Level: developer

3914:    Notes:
3915:    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3916:    call `MatSolveTranspose`(A,x,x).

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

3922: .seealso: `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3923: @*/
3924: PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3925: {
3926:   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;

3937:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3938:   MatCheckPreallocated(mat, 1);
3939:   PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0);
3940:   if (mat->factorerrortype) {
3941:     PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3942:     VecSetInf(x);
3943:   } else {
3945:     (*f)(mat, b, x);
3946:   }
3947:   PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0);
3948:   PetscObjectStateIncrease((PetscObject)x);
3949:   return 0;
3950: }

3952: /*@
3953:    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3954:                       factored matrix.

3956:    Neighbor-wise Collective

3958:    Input Parameters:
3959: +  mat - the factored matrix
3960: .  b - the right-hand-side vector
3961: -  y - the vector to be added to

3963:    Output Parameter:
3964: .  x - the result vector

3966:    Level: developer

3968:    Note:
3969:    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3970:    call `MatSolveTransposeAdd`(A,x,y,x).

3972: .seealso: `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
3973: @*/
3974: PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
3975: {
3976:   PetscScalar one = 1.0;
3977:   Vec         tmp;
3978:   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;

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

3996:   PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y);
3997:   if (mat->factorerrortype) {
3998:     PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3999:     VecSetInf(x);
4000:   } else if (f) {
4001:     (*f)(mat, b, y, x);
4002:   } else {
4003:     /* do the solve then the add manually */
4004:     if (x != y) {
4005:       MatSolveTranspose(mat, b, x);
4006:       VecAXPY(x, one, y);
4007:     } else {
4008:       VecDuplicate(x, &tmp);
4009:       VecCopy(x, tmp);
4010:       MatSolveTranspose(mat, b, x);
4011:       VecAXPY(x, one, tmp);
4012:       VecDestroy(&tmp);
4013:     }
4014:   }
4015:   PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y);
4016:   PetscObjectStateIncrease((PetscObject)x);
4017:   return 0;
4018: }

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

4023:    Neighbor-wise Collective

4025:    Input Parameters:
4026: +  mat - the matrix
4027: .  b - the right hand side
4028: .  omega - the relaxation factor
4029: .  flag - flag indicating the type of SOR (see below)
4030: .  shift -  diagonal shift
4031: .  its - the number of iterations
4032: -  lits - the number of local iterations

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

4037:    SOR Flags:
4038: +     `SOR_FORWARD_SWEEP` - forward SOR
4039: .     `SOR_BACKWARD_SWEEP` - backward SOR
4040: .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4041: .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4042: .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4043: .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4044: .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4045: .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4046:          upper/lower triangular part of matrix to
4047:          vector (with omega)
4048: -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess

4050:    Level: developer

4052:    Notes:
4053:    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4054:    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4055:    on each processor.

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

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

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

4066:    Vectors `x` and `b` CANNOT be the same

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

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

4076: .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4077: @*/
4078: PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4079: {

4095:   MatCheckPreallocated(mat, 1);
4096:   PetscLogEventBegin(MAT_SOR, mat, b, x, 0);
4097:   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4098:   PetscLogEventEnd(MAT_SOR, mat, b, x, 0);
4099:   PetscObjectStateIncrease((PetscObject)x);
4100:   return 0;
4101: }

4103: /*
4104:       Default matrix copy routine.
4105: */
4106: PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4107: {
4108:   PetscInt           i, rstart = 0, rend = 0, nz;
4109:   const PetscInt    *cwork;
4110:   const PetscScalar *vwork;

4112:   if (B->assembled) MatZeroEntries(B);
4113:   if (str == SAME_NONZERO_PATTERN) {
4114:     MatGetOwnershipRange(A, &rstart, &rend);
4115:     for (i = rstart; i < rend; i++) {
4116:       MatGetRow(A, i, &nz, &cwork, &vwork);
4117:       MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES);
4118:       MatRestoreRow(A, i, &nz, &cwork, &vwork);
4119:     }
4120:   } else {
4121:     MatAYPX(B, 0.0, A, str);
4122:   }
4123:   MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);
4124:   MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);
4125:   return 0;
4126: }

4128: /*@
4129:    MatCopy - Copies a matrix to another matrix.

4131:    Collective

4133:    Input Parameters:
4134: +  A - the matrix
4135: -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`

4137:    Output Parameter:
4138: .  B - where the copy is put

4140:    Level: intermediate

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

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

4149: .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4150: @*/
4151: PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4152: {
4153:   PetscInt i;

4160:   MatCheckPreallocated(B, 2);
4164:              A->cmap->N, B->cmap->N);
4165:   MatCheckPreallocated(A, 1);
4166:   if (A == B) return 0;

4168:   PetscLogEventBegin(MAT_Copy, A, B, 0, 0);
4169:   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4170:   else MatCopy_Basic(A, B, str);

4172:   B->stencil.dim = A->stencil.dim;
4173:   B->stencil.noc = A->stencil.noc;
4174:   for (i = 0; i <= A->stencil.dim; i++) {
4175:     B->stencil.dims[i]   = A->stencil.dims[i];
4176:     B->stencil.starts[i] = A->stencil.starts[i];
4177:   }

4179:   PetscLogEventEnd(MAT_Copy, A, B, 0, 0);
4180:   PetscObjectStateIncrease((PetscObject)B);
4181:   return 0;
4182: }

4184: /*@C
4185:    MatConvert - Converts a matrix to another matrix, either of the same
4186:    or different type.

4188:    Collective

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

4198:    Output Parameter:
4199: .  M - pointer to place new matrix

4201:    Level: intermediate

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

4208:    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4209:    the MPI communicator of the generated matrix is always the same as the communicator
4210:    of the input matrix.

4212: .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4213: @*/
4214: PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4215: {
4216:   PetscBool  sametype, issame, flg;
4217:   PetscBool3 issymmetric, ishermitian;
4218:   char       convname[256], mtype[256];
4219:   Mat        B;

4226:   MatCheckPreallocated(mat, 1);

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

4231:   PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype);
4232:   PetscStrcmp(newtype, "same", &issame);

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

4241:   /* Cache Mat options because some converters use MatHeaderReplace  */
4242:   issymmetric = mat->symmetric;
4243:   ishermitian = mat->hermitian;

4245:   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4246:     PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame);
4247:     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4248:   } else {
4249:     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4250:     const char *prefix[3]                                 = {"seq", "mpi", ""};
4251:     PetscInt    i;
4252:     /*
4253:        Order of precedence:
4254:        0) See if newtype is a superclass of the current matrix.
4255:        1) See if a specialized converter is known to the current matrix.
4256:        2) See if a specialized converter is known to the desired matrix class.
4257:        3) See if a good general converter is registered for the desired class
4258:           (as of 6/27/03 only MATMPIADJ falls into this category).
4259:        4) See if a good general converter is known for the current matrix.
4260:        5) Use a really basic converter.
4261:     */

4263:     /* 0) See if newtype is a superclass of the current matrix.
4264:           i.e mat is mpiaij and newtype is aij */
4265:     for (i = 0; i < 2; i++) {
4266:       PetscStrncpy(convname, prefix[i], sizeof(convname));
4267:       PetscStrlcat(convname, newtype, sizeof(convname));
4268:       PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg);
4269:       PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg);
4270:       if (flg) {
4271:         if (reuse == MAT_INPLACE_MATRIX) {
4272:           PetscInfo(mat, "Early return\n");
4273:           return 0;
4274:         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4275:           PetscInfo(mat, "Calling MatDuplicate\n");
4276:           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4277:           return 0;
4278:         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4279:           PetscInfo(mat, "Calling MatCopy\n");
4280:           MatCopy(mat, *M, SAME_NONZERO_PATTERN);
4281:           return 0;
4282:         }
4283:       }
4284:     }
4285:     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4286:     for (i = 0; i < 3; i++) {
4287:       PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4288:       PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4289:       PetscStrlcat(convname, "_", sizeof(convname));
4290:       PetscStrlcat(convname, prefix[i], sizeof(convname));
4291:       PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname));
4292:       PetscStrlcat(convname, "_C", sizeof(convname));
4293:       PetscObjectQueryFunction((PetscObject)mat, convname, &conv);
4294:       PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv);
4295:       if (conv) goto foundconv;
4296:     }

4298:     /* 2)  See if a specialized converter is known to the desired matrix class. */
4299:     MatCreate(PetscObjectComm((PetscObject)mat), &B);
4300:     MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
4301:     MatSetType(B, newtype);
4302:     for (i = 0; i < 3; i++) {
4303:       PetscStrncpy(convname, "MatConvert_", sizeof(convname));
4304:       PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname));
4305:       PetscStrlcat(convname, "_", sizeof(convname));
4306:       PetscStrlcat(convname, prefix[i], sizeof(convname));
4307:       PetscStrlcat(convname, newtype, sizeof(convname));
4308:       PetscStrlcat(convname, "_C", sizeof(convname));
4309:       PetscObjectQueryFunction((PetscObject)B, convname, &conv);
4310:       PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv);
4311:       if (conv) {
4312:         MatDestroy(&B);
4313:         goto foundconv;
4314:       }
4315:     }

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

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

4328:     /* 5) Use a really basic converter. */
4329:     PetscInfo(mat, "Using MatConvert_Basic\n");
4330:     conv = MatConvert_Basic;

4332:   foundconv:
4333:     PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4334:     (*conv)(mat, newtype, reuse, M);
4335:     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4336:       /* the block sizes must be same if the mappings are copied over */
4337:       (*M)->rmap->bs = mat->rmap->bs;
4338:       (*M)->cmap->bs = mat->cmap->bs;
4339:       PetscObjectReference((PetscObject)mat->rmap->mapping);
4340:       PetscObjectReference((PetscObject)mat->cmap->mapping);
4341:       (*M)->rmap->mapping = mat->rmap->mapping;
4342:       (*M)->cmap->mapping = mat->cmap->mapping;
4343:     }
4344:     (*M)->stencil.dim = mat->stencil.dim;
4345:     (*M)->stencil.noc = mat->stencil.noc;
4346:     for (i = 0; i <= mat->stencil.dim; i++) {
4347:       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4348:       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4349:     }
4350:     PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4351:   }
4352:   PetscObjectStateIncrease((PetscObject)*M);

4354:   /* Copy Mat options */
4355:   if (issymmetric == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE);
4356:   else if (issymmetric == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE);
4357:   if (ishermitian == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE);
4358:   else if (ishermitian == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE);
4359:   return 0;
4360: }

4362: /*@C
4363:    MatFactorGetSolverType - Returns name of the package providing the factorization routines

4365:    Not Collective

4367:    Input Parameter:
4368: .  mat - the matrix, must be a factored matrix

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

4373:    Level: intermediate

4375:    Fortran Note:
4376:    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.

4378: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4379: @*/
4380: PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4381: {
4382:   PetscErrorCode (*conv)(Mat, MatSolverType *);

4388:   PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv);
4389:   if (conv) (*conv)(mat, type);
4390:   else *type = MATSOLVERPETSC;
4391:   return 0;
4392: }

4394: typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4395: struct _MatSolverTypeForSpecifcType {
4396:   MatType mtype;
4397:   /* no entry for MAT_FACTOR_NONE */
4398:   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4399:   MatSolverTypeForSpecifcType next;
4400: };

4402: typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4403: struct _MatSolverTypeHolder {
4404:   char                       *name;
4405:   MatSolverTypeForSpecifcType handlers;
4406:   MatSolverTypeHolder         next;
4407: };

4409: static MatSolverTypeHolder MatSolverTypeHolders = NULL;

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

4414:    Input Parameters:
4415: +    package - name of the package, for example petsc or superlu
4416: .    mtype - the matrix type that works with this package
4417: .    ftype - the type of factorization supported by the package
4418: -    createfactor - routine that will create the factored matrix ready to be used

4420:     Level: developer

4422: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4423: @*/
4424: PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4425: {
4426:   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4427:   PetscBool                   flg;
4428:   MatSolverTypeForSpecifcType inext, iprev = NULL;

4430:   MatInitializePackage();
4431:   if (!next) {
4432:     PetscNew(&MatSolverTypeHolders);
4433:     PetscStrallocpy(package, &MatSolverTypeHolders->name);
4434:     PetscNew(&MatSolverTypeHolders->handlers);
4435:     PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype);
4436:     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4437:     return 0;
4438:   }
4439:   while (next) {
4440:     PetscStrcasecmp(package, next->name, &flg);
4441:     if (flg) {
4443:       inext = next->handlers;
4444:       while (inext) {
4445:         PetscStrcasecmp(mtype, inext->mtype, &flg);
4446:         if (flg) {
4447:           inext->createfactor[(int)ftype - 1] = createfactor;
4448:           return 0;
4449:         }
4450:         iprev = inext;
4451:         inext = inext->next;
4452:       }
4453:       PetscNew(&iprev->next);
4454:       PetscStrallocpy(mtype, (char **)&iprev->next->mtype);
4455:       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4456:       return 0;
4457:     }
4458:     prev = next;
4459:     next = next->next;
4460:   }
4461:   PetscNew(&prev->next);
4462:   PetscStrallocpy(package, &prev->next->name);
4463:   PetscNew(&prev->next->handlers);
4464:   PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype);
4465:   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4466:   return 0;
4467: }

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

4472:    Input Parameters:
4473: +    type - name of the package, for example petsc or superlu
4474: .    ftype - the type of factorization supported by the type
4475: -    mtype - the matrix type that works with this type

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

4482:     Level: developer

4484: .seealso: `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4485: @*/
4486: PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4487: {
4488:   MatSolverTypeHolder         next = MatSolverTypeHolders;
4489:   PetscBool                   flg;
4490:   MatSolverTypeForSpecifcType inext;

4492:   if (foundtype) *foundtype = PETSC_FALSE;
4493:   if (foundmtype) *foundmtype = PETSC_FALSE;
4494:   if (createfactor) *createfactor = NULL;

4496:   if (type) {
4497:     while (next) {
4498:       PetscStrcasecmp(type, next->name, &flg);
4499:       if (flg) {
4500:         if (foundtype) *foundtype = PETSC_TRUE;
4501:         inext = next->handlers;
4502:         while (inext) {
4503:           PetscStrbeginswith(mtype, inext->mtype, &flg);
4504:           if (flg) {
4505:             if (foundmtype) *foundmtype = PETSC_TRUE;
4506:             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4507:             return 0;
4508:           }
4509:           inext = inext->next;
4510:         }
4511:       }
4512:       next = next->next;
4513:     }
4514:   } else {
4515:     while (next) {
4516:       inext = next->handlers;
4517:       while (inext) {
4518:         PetscStrcmp(mtype, inext->mtype, &flg);
4519:         if (flg && inext->createfactor[(int)ftype - 1]) {
4520:           if (foundtype) *foundtype = PETSC_TRUE;
4521:           if (foundmtype) *foundmtype = PETSC_TRUE;
4522:           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4523:           return 0;
4524:         }
4525:         inext = inext->next;
4526:       }
4527:       next = next->next;
4528:     }
4529:     /* try with base classes inext->mtype */
4530:     next = MatSolverTypeHolders;
4531:     while (next) {
4532:       inext = next->handlers;
4533:       while (inext) {
4534:         PetscStrbeginswith(mtype, inext->mtype, &flg);
4535:         if (flg && inext->createfactor[(int)ftype - 1]) {
4536:           if (foundtype) *foundtype = PETSC_TRUE;
4537:           if (foundmtype) *foundmtype = PETSC_TRUE;
4538:           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4539:           return 0;
4540:         }
4541:         inext = inext->next;
4542:       }
4543:       next = next->next;
4544:     }
4545:   }
4546:   return 0;
4547: }

4549: PetscErrorCode MatSolverTypeDestroy(void)
4550: {
4551:   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4552:   MatSolverTypeForSpecifcType inext, iprev;

4554:   while (next) {
4555:     PetscFree(next->name);
4556:     inext = next->handlers;
4557:     while (inext) {
4558:       PetscFree(inext->mtype);
4559:       iprev = inext;
4560:       inext = inext->next;
4561:       PetscFree(iprev);
4562:     }
4563:     prev = next;
4564:     next = next->next;
4565:     PetscFree(prev);
4566:   }
4567:   MatSolverTypeHolders = NULL;
4568:   return 0;
4569: }

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

4574:    Logically Collective

4576:    Input Parameters:
4577: .  mat - the matrix

4579:    Output Parameters:
4580: .  flg - `PETSC_TRUE` if uses the ordering

4582:    Level: developer

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

4588: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4589: @*/
4590: PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4591: {
4592:   *flg = mat->canuseordering;
4593:   return 0;
4594: }

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

4599:    Logically Collective

4601:    Input Parameters:
4602: .  mat - the matrix obtained with `MatGetFactor()`

4604:    Output Parameters:
4605: .  otype - the preferred type

4607:    Level: developer

4609: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4610: @*/
4611: PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4612: {
4613:   *otype = mat->preferredordering[ftype];
4615:   return 0;
4616: }

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

4621:    Collective

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

4628:    Output Parameters:
4629: .  f - the factor matrix used with MatXXFactorSymbolic() calls

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

4635:    Level: intermediate

4637:    Notes:
4638:      Users usually access the factorization solvers via `KSP`

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

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

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

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

4652: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4653:           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4654: @*/
4655: PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4656: {
4657:   PetscBool foundtype, foundmtype;
4658:   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);


4664:   MatCheckPreallocated(mat, 1);

4666:   MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv);
4667:   if (!foundtype) {
4668:     if (type) {
4669:       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate solver type %s for factorization type %s and matrix type %s. Perhaps you must ./configure with --download-%s", type, MatFactorTypes[ftype],
4670:               ((PetscObject)mat)->type_name, type);
4671:     } else {
4672:       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate a solver type for factorization type %s and matrix type %s.", MatFactorTypes[ftype], ((PetscObject)mat)->type_name);
4673:     }
4674:   }

4678:   (*conv)(mat, ftype, f);
4679:   if (mat->factorprefix) MatSetOptionsPrefix(*f, mat->factorprefix);
4680:   return 0;
4681: }

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

4686:    Not Collective

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

4693:    Output Parameter:
4694: .    flg - PETSC_TRUE if the factorization is available

4696:    Level: intermediate

4698:    Notes:
4699:       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4700:      such as pastix, superlu, mumps etc.

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

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

4707: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4708:           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4709: @*/
4710: PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4711: {
4712:   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);


4719:   MatCheckPreallocated(mat, 1);

4721:   MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv);
4722:   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4723:   return 0;
4724: }

4726: /*@
4727:    MatDuplicate - Duplicates a matrix including the non-zero structure.

4729:    Collective

4731:    Input Parameters:
4732: +  mat - the matrix
4733: -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4734:         See the manual page for `MatDuplicateOption()` for an explanation of these options.

4736:    Output Parameter:
4737: .  M - pointer to place new matrix

4739:    Level: intermediate

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

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

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

4750: .seealso: `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4751: @*/
4752: PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4753: {
4754:   Mat         B;
4755:   VecType     vtype;
4756:   PetscInt    i;
4757:   PetscObject dm;
4758:   void (*viewf)(void);

4765:   MatCheckPreallocated(mat, 1);

4767:   *M = NULL;
4768:   PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4769:   PetscUseTypeMethod(mat, duplicate, op, M);
4770:   PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4771:   B = *M;

4773:   MatGetOperation(mat, MATOP_VIEW, &viewf);
4774:   if (viewf) MatSetOperation(B, MATOP_VIEW, viewf);
4775:   MatGetVecType(mat, &vtype);
4776:   MatSetVecType(B, vtype);

4778:   B->stencil.dim = mat->stencil.dim;
4779:   B->stencil.noc = mat->stencil.noc;
4780:   for (i = 0; i <= mat->stencil.dim; i++) {
4781:     B->stencil.dims[i]   = mat->stencil.dims[i];
4782:     B->stencil.starts[i] = mat->stencil.starts[i];
4783:   }

4785:   B->nooffproczerorows = mat->nooffproczerorows;
4786:   B->nooffprocentries  = mat->nooffprocentries;

4788:   PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm);
4789:   if (dm) PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm);
4790:   PetscObjectStateIncrease((PetscObject)B);
4791:   return 0;
4792: }

4794: /*@
4795:    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`

4797:    Logically Collective

4799:    Input Parameters:
4800: +  mat - the matrix
4801: -  v - the vector for storing the diagonal

4803:    Output Parameter:
4804: .  v - the diagonal of the matrix

4806:    Level: intermediate

4808:    Note:
4809:    Currently only correct in parallel for square matrices.

4811: .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4812: @*/
4813: PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4814: {
4819:   MatCheckPreallocated(mat, 1);

4821:   PetscUseTypeMethod(mat, getdiagonal, v);
4822:   PetscObjectStateIncrease((PetscObject)v);
4823:   return 0;
4824: }

4826: /*@C
4827:    MatGetRowMin - Gets the minimum value (of the real part) of each
4828:         row of the matrix

4830:    Logically Collective

4832:    Input Parameter:
4833: .  mat - the matrix

4835:    Output Parameters:
4836: +  v - the vector for storing the maximums
4837: -  idx - the indices of the column found for each row (optional)

4839:    Level: intermediate

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

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

4847: .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4848:           `MatGetRowMax()`
4849: @*/
4850: PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4851: {

4857:   if (!mat->cmap->N) {
4858:     VecSet(v, PETSC_MAX_REAL);
4859:     if (idx) {
4860:       PetscInt i, m = mat->rmap->n;
4861:       for (i = 0; i < m; i++) idx[i] = -1;
4862:     }
4863:   } else {
4864:     MatCheckPreallocated(mat, 1);
4865:   }
4866:   PetscUseTypeMethod(mat, getrowmin, v, idx);
4867:   PetscObjectStateIncrease((PetscObject)v);
4868:   return 0;
4869: }

4871: /*@C
4872:    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4873:         row of the matrix

4875:    Logically Collective

4877:    Input Parameter:
4878: .  mat - the matrix

4880:    Output Parameters:
4881: +  v - the vector for storing the minimums
4882: -  idx - the indices of the column found for each row (or `NULL` if not needed)

4884:    Level: intermediate

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

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

4892: .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4893: @*/
4894: PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4895: {

4902:   if (!mat->cmap->N) {
4903:     VecSet(v, 0.0);
4904:     if (idx) {
4905:       PetscInt i, m = mat->rmap->n;
4906:       for (i = 0; i < m; i++) idx[i] = -1;
4907:     }
4908:   } else {
4909:     MatCheckPreallocated(mat, 1);
4910:     if (idx) PetscArrayzero(idx, mat->rmap->n);
4911:     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4912:   }
4913:   PetscObjectStateIncrease((PetscObject)v);
4914:   return 0;
4915: }

4917: /*@C
4918:    MatGetRowMax - Gets the maximum value (of the real part) of each
4919:         row of the matrix

4921:    Logically Collective

4923:    Input Parameter:
4924: .  mat - the matrix

4926:    Output Parameters:
4927: +  v - the vector for storing the maximums
4928: -  idx - the indices of the column found for each row (optional)

4930:    Level: intermediate

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

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

4938: .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4939: @*/
4940: PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
4941: {

4947:   if (!mat->cmap->N) {
4948:     VecSet(v, PETSC_MIN_REAL);
4949:     if (idx) {
4950:       PetscInt i, m = mat->rmap->n;
4951:       for (i = 0; i < m; i++) idx[i] = -1;
4952:     }
4953:   } else {
4954:     MatCheckPreallocated(mat, 1);
4955:     PetscUseTypeMethod(mat, getrowmax, v, idx);
4956:   }
4957:   PetscObjectStateIncrease((PetscObject)v);
4958:   return 0;
4959: }

4961: /*@C
4962:    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4963:         row of the matrix

4965:    Logically Collective

4967:    Input Parameter:
4968: .  mat - the matrix

4970:    Output Parameters:
4971: +  v - the vector for storing the maximums
4972: -  idx - the indices of the column found for each row (or `NULL` if not needed)

4974:    Level: intermediate

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

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

4982: .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4983: @*/
4984: PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
4985: {

4991:   if (!mat->cmap->N) {
4992:     VecSet(v, 0.0);
4993:     if (idx) {
4994:       PetscInt i, m = mat->rmap->n;
4995:       for (i = 0; i < m; i++) idx[i] = -1;
4996:     }
4997:   } else {
4998:     MatCheckPreallocated(mat, 1);
4999:     if (idx) PetscArrayzero(idx, mat->rmap->n);
5000:     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5001:   }
5002:   PetscObjectStateIncrease((PetscObject)v);
5003:   return 0;
5004: }

5006: /*@
5007:    MatGetRowSum - Gets the sum of each row of the matrix

5009:    Logically or Neighborhood Collective

5011:    Input Parameters:
5012: .  mat - the matrix

5014:    Output Parameter:
5015: .  v - the vector for storing the sum of rows

5017:    Level: intermediate

5019:    Notes:
5020:     This code is slow since it is not currently specialized for different formats

5022: .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5023: @*/
5024: PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5025: {
5026:   Vec ones;

5032:   MatCheckPreallocated(mat, 1);
5033:   MatCreateVecs(mat, &ones, NULL);
5034:   VecSet(ones, 1.);
5035:   MatMult(mat, ones, v);
5036:   VecDestroy(&ones);
5037:   return 0;
5038: }

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

5044:    Collective

5046:    Input Parameter:
5047: .  mat - the matrix to provide the transpose

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

5052:    Level: advanced

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

5058: .seealso: `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5059: @*/
5060: PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5061: {
5062:   PetscContainer  rB = NULL;
5063:   MatParentState *rb = NULL;

5065:   PetscNew(&rb);
5066:   rb->id    = ((PetscObject)mat)->id;
5067:   rb->state = 0;
5068:   MatGetNonzeroState(mat, &rb->nonzerostate);
5069:   PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB);
5070:   PetscContainerSetPointer(rB, rb);
5071:   PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault);
5072:   PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB);
5073:   PetscObjectDereference((PetscObject)rB);
5074:   return 0;
5075: }

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

5080:    Collective

5082:    Input Parameters:
5083: +  mat - the matrix to transpose
5084: -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`

5086:    Output Parameter:
5087: .  B - the transpose

5089:    Level: intermediate

5091:    Notes:
5092:      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B

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

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

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

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

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

5105: .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5106:           `MatTransposeSymbolic()`
5107: @*/
5108: PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5109: {
5110:   PetscContainer  rB = NULL;
5111:   MatParentState *rb = NULL;

5119:   MatCheckPreallocated(mat, 1);
5120:   if (reuse == MAT_REUSE_MATRIX) {
5121:     PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5123:     PetscContainerGetPointer(rB, (void **)&rb);
5125:     if (rb->state == ((PetscObject)mat)->state) return 0;
5126:   }

5128:   PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0);
5129:   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5130:     PetscUseTypeMethod(mat, transpose, reuse, B);
5131:     PetscObjectStateIncrease((PetscObject)*B);
5132:   }
5133:   PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0);

5135:   if (reuse == MAT_INITIAL_MATRIX) MatTransposeSetPrecursor(mat, *B);
5136:   if (reuse != MAT_INPLACE_MATRIX) {
5137:     PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5138:     PetscContainerGetPointer(rB, (void **)&rb);
5139:     rb->state        = ((PetscObject)mat)->state;
5140:     rb->nonzerostate = mat->nonzerostate;
5141:   }
5142:   return 0;
5143: }

5145: /*@
5146:    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.

5148:    Collective

5150:    Input Parameters:
5151: .  A - the matrix to transpose

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

5157:    Level: intermediate

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

5162: .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5163: @*/
5164: PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5165: {
5171:   PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0);
5172:   (*A->ops->transposesymbolic)(A, B);
5173:   PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0);

5175:   MatTransposeSetPrecursor(A, *B);
5176:   return 0;
5177: }

5179: PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5180: {
5181:   PetscContainer  rB;
5182:   MatParentState *rb;

5188:   PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB);
5190:   PetscContainerGetPointer(rB, (void **)&rb);
5193:   return 0;
5194: }

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

5200:    Collective

5202:    Input Parameters:
5203: +  A - the matrix to test
5204: -  B - the matrix to test against, this can equal the first parameter

5206:    Output Parameters:
5207: .  flg - the result

5209:    Level: intermediate

5211:    Notes:
5212:    Only available for `MATAIJ` matrices.

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

5217: .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5218: @*/
5219: PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5220: {
5221:   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);

5226:   PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f);
5227:   PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g);
5228:   *flg = PETSC_FALSE;
5229:   if (f && g) {
5231:     (*f)(A, B, tol, flg);
5232:   } else {
5233:     MatType mattype;

5235:     MatGetType(f ? B : A, &mattype);
5236:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5237:   }
5238:   return 0;
5239: }

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

5244:    Collective

5246:    Input Parameters:
5247: +  mat - the matrix to transpose and complex conjugate
5248: -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`

5250:    Output Parameter:
5251: .  B - the Hermitian transpose

5253:    Level: intermediate

5255: .seealso: `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5256: @*/
5257: PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5258: {
5259:   MatTranspose(mat, reuse, B);
5260: #if defined(PETSC_USE_COMPLEX)
5261:   MatConjugate(*B);
5262: #endif
5263:   return 0;
5264: }

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

5269:    Collective

5271:    Input Parameters:
5272: +  A - the matrix to test
5273: -  B - the matrix to test against, this can equal the first parameter

5275:    Output Parameters:
5276: .  flg - the result

5278:    Level: intermediate

5280:    Notes:
5281:    Only available for `MATAIJ` matrices.

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

5287: .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5288: @*/
5289: PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5290: {
5291:   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);

5296:   PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f);
5297:   PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g);
5298:   if (f && g) {
5300:     (*f)(A, B, tol, flg);
5301:   }
5302:   return 0;
5303: }

5305: /*@
5306:    MatPermute - Creates a new matrix with rows and columns permuted from the
5307:    original.

5309:    Collective

5311:    Input Parameters:
5312: +  mat - the matrix to permute
5313: .  row - row permutation, each processor supplies only the permutation for its rows
5314: -  col - column permutation, each processor supplies only the permutation for its columns

5316:    Output Parameters:
5317: .  B - the permuted matrix

5319:    Level: advanced

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

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

5330: .seealso: `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5331: @*/
5332: PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5333: {
5344:   MatCheckPreallocated(mat, 1);

5346:   if (mat->ops->permute) {
5347:     PetscUseTypeMethod(mat, permute, row, col, B);
5348:     PetscObjectStateIncrease((PetscObject)*B);
5349:   } else {
5350:     MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B);
5351:   }
5352:   return 0;
5353: }

5355: /*@
5356:    MatEqual - Compares two matrices.

5358:    Collective

5360:    Input Parameters:
5361: +  A - the first matrix
5362: -  B - the second matrix

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

5367:    Level: intermediate

5369: .seealso: `Mat`
5370: @*/
5371: PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5372: {
5379:   MatCheckPreallocated(A, 1);
5380:   MatCheckPreallocated(B, 2);
5384:              B->cmap->N);
5385:   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5386:     PetscUseTypeMethod(A, equal, B, flg);
5387:   } else {
5388:     MatMultEqual(A, B, 10, flg);
5389:   }
5390:   return 0;
5391: }

5393: /*@
5394:    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5395:    matrices that are stored as vectors.  Either of the two scaling
5396:    matrices can be `NULL`.

5398:    Collective

5400:    Input Parameters:
5401: +  mat - the matrix to be scaled
5402: .  l - the left scaling vector (or `NULL`)
5403: -  r - the right scaling vector (or `NULL`)

5405:    Level: intermediate

5407:    Note:
5408:    `MatDiagonalScale()` computes A = LAR, where
5409:    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5410:    The L scales the rows of the matrix, the R scales the columns of the matrix.

5412: .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5413: @*/
5414: PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5415: {
5418:   if (l) {
5421:   }
5422:   if (r) {
5425:   }
5428:   MatCheckPreallocated(mat, 1);
5429:   if (!l && !r) return 0;

5431:   PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5432:   PetscUseTypeMethod(mat, diagonalscale, l, r);
5433:   PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5434:   PetscObjectStateIncrease((PetscObject)mat);
5435:   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5436:   return 0;
5437: }

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

5442:     Logically Collective

5444:     Input Parameters:
5445: +   mat - the matrix to be scaled
5446: -   a  - the scaling value

5448:     Output Parameter:
5449: .   mat - the scaled matrix

5451:     Level: intermediate

5453: .seealso: `Mat`, `MatDiagonalScale()`
5454: @*/
5455: PetscErrorCode MatScale(Mat mat, PetscScalar a)
5456: {
5463:   MatCheckPreallocated(mat, 1);

5465:   PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5466:   if (a != (PetscScalar)1.0) {
5467:     PetscUseTypeMethod(mat, scale, a);
5468:     PetscObjectStateIncrease((PetscObject)mat);
5469:   }
5470:   PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5471:   return 0;
5472: }

5474: /*@
5475:    MatNorm - Calculates various norms of a matrix.

5477:    Collective

5479:    Input Parameters:
5480: +  mat - the matrix
5481: -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`

5483:    Output Parameter:
5484: .  nrm - the resulting norm

5486:    Level: intermediate

5488: .seealso: `Mat`
5489: @*/
5490: PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5491: {

5498:   MatCheckPreallocated(mat, 1);

5500:   PetscUseTypeMethod(mat, norm, type, nrm);
5501:   return 0;
5502: }

5504: /*
5505:      This variable is used to prevent counting of MatAssemblyBegin() that
5506:    are called from within a MatAssemblyEnd().
5507: */
5508: static PetscInt MatAssemblyEnd_InUse = 0;
5509: /*@
5510:    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5511:    be called after completing all calls to `MatSetValues()`.

5513:    Collective

5515:    Input Parameters:
5516: +  mat - the matrix
5517: -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`

5519:    Level: beginner

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

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

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

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

5537: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5538: @*/
5539: PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5540: {
5543:   MatCheckPreallocated(mat, 1);
5545:   if (mat->assembled) {
5546:     mat->was_assembled = PETSC_TRUE;
5547:     mat->assembled     = PETSC_FALSE;
5548:   }

5550:   if (!MatAssemblyEnd_InUse) {
5551:     PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0);
5552:     PetscTryTypeMethod(mat, assemblybegin, type);
5553:     PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0);
5554:   } else PetscTryTypeMethod(mat, assemblybegin, type);
5555:   return 0;
5556: }

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

5562:    Not Collective

5564:    Input Parameter:
5565: .  mat - the matrix

5567:    Output Parameter:
5568: .  assembled - `PETSC_TRUE` or `PETSC_FALSE`

5570:    Level: advanced

5572: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5573: @*/
5574: PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5575: {
5578:   *assembled = mat->assembled;
5579:   return 0;
5580: }

5582: /*@
5583:    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5584:    be called after `MatAssemblyBegin()`.

5586:    Collective on Mat

5588:    Input Parameters:
5589: +  mat - the matrix
5590: -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`

5592:    Options Database Keys:
5593: +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5594: .  -mat_view ::ascii_info_detail - Prints more detailed info
5595: .  -mat_view - Prints matrix in ASCII format
5596: .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5597: .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5598: .  -display <name> - Sets display name (default is host)
5599: .  -draw_pause <sec> - Sets number of seconds to pause after display
5600: .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5601: .  -viewer_socket_machine <machine> - Machine to use for socket
5602: .  -viewer_socket_port <port> - Port number to use for socket
5603: -  -mat_view binary:filename[:append] - Save matrix to file in binary format

5605:    Level: beginner

5607: .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5608: @*/
5609: PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5610: {
5611:   static PetscInt inassm = 0;
5612:   PetscBool       flg    = PETSC_FALSE;


5617:   inassm++;
5618:   MatAssemblyEnd_InUse++;
5619:   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5620:     PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0);
5621:     PetscTryTypeMethod(mat, assemblyend, type);
5622:     PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0);
5623:   } else PetscTryTypeMethod(mat, assemblyend, type);

5625:   /* Flush assembly is not a true assembly */
5626:   if (type != MAT_FLUSH_ASSEMBLY) {
5627:     if (mat->num_ass) {
5628:       if (!mat->symmetry_eternal) {
5629:         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5630:         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5631:       }
5632:       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5633:       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5634:     }
5635:     mat->num_ass++;
5636:     mat->assembled        = PETSC_TRUE;
5637:     mat->ass_nonzerostate = mat->nonzerostate;
5638:   }

5640:   mat->insertmode = NOT_SET_VALUES;
5641:   MatAssemblyEnd_InUse--;
5642:   PetscObjectStateIncrease((PetscObject)mat);
5643:   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5644:     MatViewFromOptions(mat, NULL, "-mat_view");

5646:     if (mat->checksymmetryonassembly) {
5647:       MatIsSymmetric(mat, mat->checksymmetrytol, &flg);
5648:       if (flg) {
5649:         PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5650:       } else {
5651:         PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5652:       }
5653:     }
5654:     if (mat->nullsp && mat->checknullspaceonassembly) MatNullSpaceTest(mat->nullsp, mat, NULL);
5655:   }
5656:   inassm--;
5657:   return 0;
5658: }

5660: /*@
5661:    MatSetOption - Sets a parameter option for a matrix. Some options
5662:    may be specific to certain storage formats.  Some options
5663:    determine how values will be inserted (or added). Sorted,
5664:    row-oriented input will generally assemble the fastest. The default
5665:    is row-oriented.

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

5669:    Input Parameters:
5670: +  mat - the matrix
5671: .  option - the option, one of those listed below (and possibly others),
5672: -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)

5674:   Options Describing Matrix Structure:
5675: +    `MAT_SPD` - symmetric positive definite
5676: .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5677: .    `MAT_HERMITIAN` - transpose is the complex conjugation
5678: .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5679: .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5680: .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5681: -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix

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

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

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

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

5708:    Level: intermediate

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

5713:    Some options are relevant only for particular matrix types and
5714:    are thus ignored by others.  Other options are not supported by
5715:    certain matrix types and will generate an error message if set.

5717:    If using Fortran to compute a matrix, one may need to
5718:    use the column-oriented option (or convert to the row-oriented
5719:    format).

5721:    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5722:    that would generate a new entry in the nonzero structure is instead
5723:    ignored.  Thus, if memory has not already been allocated for this particular
5724:    data, then the insertion is ignored. For dense matrices, in which
5725:    the entire array is allocated, no entries are ever ignored.
5726:    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction

5728:    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5729:    that would generate a new entry in the nonzero structure instead produces
5730:    an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats only.) If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction

5732:    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5733:    that would generate a new entry that has not been preallocated will
5734:    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5735:    only.) This is a useful flag when debugging matrix memory preallocation.
5736:    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction

5738:    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5739:    other processors should be dropped, rather than stashed.
5740:    This is useful if you know that the "owning" processor is also
5741:    always generating the correct matrix entries, so that PETSc need
5742:    not transfer duplicate entries generated on another processor.

5744:    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5745:    searches during matrix assembly. When this flag is set, the hash table
5746:    is created during the first matrix assembly. This hash table is
5747:    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5748:    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5749:    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5750:    supported by `MATMPIBAIJ` format only.

5752:    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5753:    are kept in the nonzero structure

5755:    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5756:    a zero location in the matrix

5758:    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types

5760:    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5761:         zero row routines and thus improves performance for very large process counts.

5763:    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5764:         part of the matrix (since they should match the upper triangular part).

5766:    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5767:                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5768:                      with finite difference schemes with non-periodic boundary conditions.

5770:    Developer Note:
5771:    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5772:    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5773:    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5774:    not changed.

5776: .seealso: `MatOption`, `Mat`, `MatGetOption()`
5777: @*/
5778: PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5779: {
5781:   if (op > 0) {
5784:   }


5788:   switch (op) {
5789:   case MAT_FORCE_DIAGONAL_ENTRIES:
5790:     mat->force_diagonals = flg;
5791:     return 0;
5792:   case MAT_NO_OFF_PROC_ENTRIES:
5793:     mat->nooffprocentries = flg;
5794:     return 0;
5795:   case MAT_SUBSET_OFF_PROC_ENTRIES:
5796:     mat->assembly_subset = flg;
5797:     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5798: #if !defined(PETSC_HAVE_MPIUNI)
5799:       MatStashScatterDestroy_BTS(&mat->stash);
5800: #endif
5801:       mat->stash.first_assembly_done = PETSC_FALSE;
5802:     }
5803:     return 0;
5804:   case MAT_NO_OFF_PROC_ZERO_ROWS:
5805:     mat->nooffproczerorows = flg;
5806:     return 0;
5807:   case MAT_SPD:
5808:     if (flg) {
5809:       mat->spd                    = PETSC_BOOL3_TRUE;
5810:       mat->symmetric              = PETSC_BOOL3_TRUE;
5811:       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5812:     } else {
5813:       mat->spd = PETSC_BOOL3_FALSE;
5814:     }
5815:     break;
5816:   case MAT_SYMMETRIC:
5817:     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5818:     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5819: #if !defined(PETSC_USE_COMPLEX)
5820:     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5821: #endif
5822:     break;
5823:   case MAT_HERMITIAN:
5824:     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5825:     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5826: #if !defined(PETSC_USE_COMPLEX)
5827:     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5828: #endif
5829:     break;
5830:   case MAT_STRUCTURALLY_SYMMETRIC:
5831:     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5832:     break;
5833:   case MAT_SYMMETRY_ETERNAL:
5835:     mat->symmetry_eternal = flg;
5836:     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5837:     break;
5838:   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5840:     mat->structural_symmetry_eternal = flg;
5841:     break;
5842:   case MAT_SPD_ETERNAL:
5844:     mat->spd_eternal = flg;
5845:     if (flg) {
5846:       mat->structural_symmetry_eternal = PETSC_TRUE;
5847:       mat->symmetry_eternal            = PETSC_TRUE;
5848:     }
5849:     break;
5850:   case MAT_STRUCTURE_ONLY:
5851:     mat->structure_only = flg;
5852:     break;
5853:   case MAT_SORTED_FULL:
5854:     mat->sortedfull = flg;
5855:     break;
5856:   default:
5857:     break;
5858:   }
5859:   PetscTryTypeMethod(mat, setoption, op, flg);
5860:   return 0;
5861: }

5863: /*@
5864:    MatGetOption - Gets a parameter option that has been set for a matrix.

5866:    Logically Collective

5868:    Input Parameters:
5869: +  mat - the matrix
5870: -  option - the option, this only responds to certain options, check the code for which ones

5872:    Output Parameter:
5873: .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)

5875:    Level: intermediate

5877:     Notes:
5878:     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.

5880:     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5881:     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`

5883: .seealso: `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5884:     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5885: @*/
5886: PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5887: {


5894:   switch (op) {
5895:   case MAT_NO_OFF_PROC_ENTRIES:
5896:     *flg = mat->nooffprocentries;
5897:     break;
5898:   case MAT_NO_OFF_PROC_ZERO_ROWS:
5899:     *flg = mat->nooffproczerorows;
5900:     break;
5901:   case MAT_SYMMETRIC:
5902:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5903:     break;
5904:   case MAT_HERMITIAN:
5905:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5906:     break;
5907:   case MAT_STRUCTURALLY_SYMMETRIC:
5908:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5909:     break;
5910:   case MAT_SPD:
5911:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
5912:     break;
5913:   case MAT_SYMMETRY_ETERNAL:
5914:     *flg = mat->symmetry_eternal;
5915:     break;
5916:   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5917:     *flg = mat->symmetry_eternal;
5918:     break;
5919:   default:
5920:     break;
5921:   }
5922:   return 0;
5923: }

5925: /*@
5926:    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5927:    this routine retains the old nonzero structure.

5929:    Logically Collective

5931:    Input Parameters:
5932: .  mat - the matrix

5934:    Level: intermediate

5936:    Note:
5937:     If the matrix was not preallocated then a default, likely poor preallocation will be set in the matrix, so this should be called after the preallocation phase.
5938:    See the Performance chapter of the users manual for information on preallocating matrices.

5940: .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
5941: @*/
5942: PetscErrorCode MatZeroEntries(Mat mat)
5943: {
5948:   MatCheckPreallocated(mat, 1);

5950:   PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0);
5951:   PetscUseTypeMethod(mat, zeroentries);
5952:   PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0);
5953:   PetscObjectStateIncrease((PetscObject)mat);
5954:   return 0;
5955: }

5957: /*@
5958:    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5959:    of a set of rows and columns of a matrix.

5961:    Collective

5963:    Input Parameters:
5964: +  mat - the matrix
5965: .  numRows - the number of rows/columns to zero
5966: .  rows - the global row indices
5967: .  diag - value put in the diagonal of the eliminated rows
5968: .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
5969: -  b - optional vector of the right hand side, that will be adjusted by provided solution entries

5971:    Level: intermediate

5973:    Notes:
5974:    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.

5976:    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
5977:    The other entries of `b` will be adjusted by the known values of `x` times the corresponding matrix entries in the columns that are being eliminated

5979:    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5980:    Krylov method to take advantage of the known solution on the zeroed rows.

5982:    For the parallel case, all processes that share the matrix (i.e.,
5983:    those in the communicator used for matrix creation) MUST call this
5984:    routine, regardless of whether any rows being zeroed are owned by
5985:    them.

5987:    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.

5989:    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5990:    list only rows local to itself).

5992:    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.

5994: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5995:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5996: @*/
5997: PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
5998: {
6004:   MatCheckPreallocated(mat, 1);

6006:   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6007:   MatViewFromOptions(mat, NULL, "-mat_view");
6008:   PetscObjectStateIncrease((PetscObject)mat);
6009:   return 0;
6010: }

6012: /*@
6013:    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6014:    of a set of rows and columns of a matrix.

6016:    Collective

6018:    Input Parameters:
6019: +  mat - the matrix
6020: .  is - the rows to zero
6021: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6022: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6023: -  b - optional vector of right hand side, that will be adjusted by provided solution

6025:    Level: intermediate

6027:    Note:
6028:    See `MatZeroRowsColumns()` for details on how this routine operates.

6030: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6031:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6032: @*/
6033: PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6034: {
6035:   PetscInt        numRows;
6036:   const PetscInt *rows;

6042:   ISGetLocalSize(is, &numRows);
6043:   ISGetIndices(is, &rows);
6044:   MatZeroRowsColumns(mat, numRows, rows, diag, x, b);
6045:   ISRestoreIndices(is, &rows);
6046:   return 0;
6047: }

6049: /*@
6050:    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6051:    of a set of rows of a matrix.

6053:    Collective

6055:    Input Parameters:
6056: +  mat - the matrix
6057: .  numRows - the number of rows to zero
6058: .  rows - the global row indices
6059: .  diag - value put in the diagonal of the zeroed rows
6060: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6061: -  b - optional vector of right hand side, that will be adjusted by provided solution entries

6063:    Level: intermediate

6065:    Notes:
6066:    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.

6068:    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.

6070:    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6071:    Krylov method to take advantage of the known solution on the zeroed rows.

6073:    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reduced problem (`PCDISTRIBUTE` completely eliminates the zeroed rows and their corresponding columns)
6074:    from the matrix.

6076:    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6077:    but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal
6078:    formats this does not alter the nonzero structure.

6080:    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6081:    of the matrix is not changed the values are
6082:    merely zeroed.

6084:    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6085:    formats can optionally remove the main diagonal entry from the
6086:    nonzero structure as well, by passing 0.0 as the final argument).

6088:    For the parallel case, all processes that share the matrix (i.e.,
6089:    those in the communicator used for matrix creation) MUST call this
6090:    routine, regardless of whether any rows being zeroed are owned by
6091:    them.

6093:    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6094:    list only rows local to itself).

6096:    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6097:    owns that are to be zeroed. This saves a global synchronization in the implementation.

6099: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6100:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6101: @*/
6102: PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6103: {
6109:   MatCheckPreallocated(mat, 1);

6111:   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6112:   MatViewFromOptions(mat, NULL, "-mat_view");
6113:   PetscObjectStateIncrease((PetscObject)mat);
6114:   return 0;
6115: }

6117: /*@
6118:    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6119:    of a set of rows of a matrix.

6121:    Collective on Mat

6123:    Input Parameters:
6124: +  mat - the matrix
6125: .  is - index set of rows to remove (if `NULL` then no row is removed)
6126: .  diag - value put in all diagonals of eliminated rows
6127: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6128: -  b - optional vector of right hand side, that will be adjusted by provided solution

6130:    Level: intermediate

6132:    Note:
6133:    See `MatZeroRows()` for details on how this routine operates.

6135: .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6136:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6137: @*/
6138: PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6139: {
6140:   PetscInt        numRows = 0;
6141:   const PetscInt *rows    = NULL;

6145:   if (is) {
6147:     ISGetLocalSize(is, &numRows);
6148:     ISGetIndices(is, &rows);
6149:   }
6150:   MatZeroRows(mat, numRows, rows, diag, x, b);
6151:   if (is) ISRestoreIndices(is, &rows);
6152:   return 0;
6153: }

6155: /*@
6156:    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6157:    of a set of rows of a matrix. These rows must be local to the process.

6159:    Collective

6161:    Input Parameters:
6162: +  mat - the matrix
6163: .  numRows - the number of rows to remove
6164: .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6165: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6166: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6167: -  b - optional vector of right hand side, that will be adjusted by provided solution

6169:    Level: intermediate

6171:    Notes:
6172:    See `MatZeroRows()` for details on how this routine operates.

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

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

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

6184:    Fortran Note:
6185:    idxm and idxn should be declared as
6186: $     MatStencil idxm(4,m)
6187:    and the values inserted using
6188: .vb
6189:     idxm(MatStencil_i,1) = i
6190:     idxm(MatStencil_j,1) = j
6191:     idxm(MatStencil_k,1) = k
6192:     idxm(MatStencil_c,1) = c
6193:    etc
6194: .ve

6196: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6197:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6198: @*/
6199: PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6200: {
6201:   PetscInt  dim    = mat->stencil.dim;
6202:   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6203:   PetscInt *dims   = mat->stencil.dims + 1;
6204:   PetscInt *starts = mat->stencil.starts;
6205:   PetscInt *dxm    = (PetscInt *)rows;
6206:   PetscInt *jdxm, i, j, tmp, numNewRows = 0;


6212:   PetscMalloc1(numRows, &jdxm);
6213:   for (i = 0; i < numRows; ++i) {
6214:     /* Skip unused dimensions (they are ordered k, j, i, c) */
6215:     for (j = 0; j < 3 - sdim; ++j) dxm++;
6216:     /* Local index in X dir */
6217:     tmp = *dxm++ - starts[0];
6218:     /* Loop over remaining dimensions */
6219:     for (j = 0; j < dim - 1; ++j) {
6220:       /* If nonlocal, set index to be negative */
6221:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6222:       /* Update local index */
6223:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6224:     }
6225:     /* Skip component slot if necessary */
6226:     if (mat->stencil.noc) dxm++;
6227:     /* Local row number */
6228:     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6229:   }
6230:   MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b);
6231:   PetscFree(jdxm);
6232:   return 0;
6233: }

6235: /*@
6236:    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6237:    of a set of rows and columns of a matrix.

6239:    Collective

6241:    Input Parameters:
6242: +  mat - the matrix
6243: .  numRows - the number of rows/columns to remove
6244: .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6245: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6246: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6247: -  b - optional vector of right hand side, that will be adjusted by provided solution

6249:    Level: intermediate

6251:    Notes:
6252:    See `MatZeroRowsColumns()` for details on how this routine operates.

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

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

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

6264:    Fortran Note:
6265:    In Fortran idxm and idxn should be declared as
6266: $     MatStencil idxm(4,m)
6267:    and the values inserted using
6268: .vb
6269:     idxm(MatStencil_i,1) = i
6270:     idxm(MatStencil_j,1) = j
6271:     idxm(MatStencil_k,1) = k
6272:     idxm(MatStencil_c,1) = c
6273:     etc
6274: .ve

6276: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6277:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6278: @*/
6279: PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6280: {
6281:   PetscInt  dim    = mat->stencil.dim;
6282:   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6283:   PetscInt *dims   = mat->stencil.dims + 1;
6284:   PetscInt *starts = mat->stencil.starts;
6285:   PetscInt *dxm    = (PetscInt *)rows;
6286:   PetscInt *jdxm, i, j, tmp, numNewRows = 0;


6292:   PetscMalloc1(numRows, &jdxm);
6293:   for (i = 0; i < numRows; ++i) {
6294:     /* Skip unused dimensions (they are ordered k, j, i, c) */
6295:     for (j = 0; j < 3 - sdim; ++j) dxm++;
6296:     /* Local index in X dir */
6297:     tmp = *dxm++ - starts[0];
6298:     /* Loop over remaining dimensions */
6299:     for (j = 0; j < dim - 1; ++j) {
6300:       /* If nonlocal, set index to be negative */
6301:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6302:       /* Update local index */
6303:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6304:     }
6305:     /* Skip component slot if necessary */
6306:     if (mat->stencil.noc) dxm++;
6307:     /* Local row number */
6308:     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6309:   }
6310:   MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b);
6311:   PetscFree(jdxm);
6312:   return 0;
6313: }

6315: /*@C
6316:    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6317:    of a set of rows of a matrix; using local numbering of rows.

6319:    Collective

6321:    Input Parameters:
6322: +  mat - the matrix
6323: .  numRows - the number of rows to remove
6324: .  rows - the local row indices
6325: .  diag - value put in all diagonals of eliminated rows
6326: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6327: -  b - optional vector of right hand side, that will be adjusted by provided solution

6329:    Level: intermediate

6331:    Notes:
6332:    Before calling `MatZeroRowsLocal()`, the user must first set the
6333:    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.

6335:    See `MatZeroRows()` for details on how this routine operates.

6337: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6338:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6339: @*/
6340: PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6341: {
6347:   MatCheckPreallocated(mat, 1);

6349:   if (mat->ops->zerorowslocal) {
6350:     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6351:   } else {
6352:     IS              is, newis;
6353:     const PetscInt *newRows;

6356:     ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6357:     ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis);
6358:     ISGetIndices(newis, &newRows);
6359:     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6360:     ISRestoreIndices(newis, &newRows);
6361:     ISDestroy(&newis);
6362:     ISDestroy(&is);
6363:   }
6364:   PetscObjectStateIncrease((PetscObject)mat);
6365:   return 0;
6366: }

6368: /*@
6369:    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6370:    of a set of rows of a matrix; using local numbering of rows.

6372:    Collective

6374:    Input Parameters:
6375: +  mat - the matrix
6376: .  is - index set of rows to remove
6377: .  diag - value put in all diagonals of eliminated rows
6378: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6379: -  b - optional vector of right hand side, that will be adjusted by provided solution

6381:    Level: intermediate

6383:    Notes:
6384:    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6385:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6387:    See `MatZeroRows()` for details on how this routine operates.

6389: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6390:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6391: @*/
6392: PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6393: {
6394:   PetscInt        numRows;
6395:   const PetscInt *rows;

6402:   MatCheckPreallocated(mat, 1);

6404:   ISGetLocalSize(is, &numRows);
6405:   ISGetIndices(is, &rows);
6406:   MatZeroRowsLocal(mat, numRows, rows, diag, x, b);
6407:   ISRestoreIndices(is, &rows);
6408:   return 0;
6409: }

6411: /*@
6412:    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6413:    of a set of rows and columns of a matrix; using local numbering of rows.

6415:    Collective

6417:    Input Parameters:
6418: +  mat - the matrix
6419: .  numRows - the number of rows to remove
6420: .  rows - the global row indices
6421: .  diag - value put in all diagonals of eliminated rows
6422: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6423: -  b - optional vector of right hand side, that will be adjusted by provided solution

6425:    Level: intermediate

6427:    Notes:
6428:    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6429:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6431:    See `MatZeroRowsColumns()` for details on how this routine operates.

6433: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6434:           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6435: @*/
6436: PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6437: {
6438:   IS              is, newis;
6439:   const PetscInt *newRows;

6446:   MatCheckPreallocated(mat, 1);

6449:   ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6450:   ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis);
6451:   ISGetIndices(newis, &newRows);
6452:   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6453:   ISRestoreIndices(newis, &newRows);
6454:   ISDestroy(&newis);
6455:   ISDestroy(&is);
6456:   PetscObjectStateIncrease((PetscObject)mat);
6457:   return 0;
6458: }

6460: /*@
6461:    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6462:    of a set of rows and columns of a matrix; using local numbering of rows.

6464:    Collective on Mat

6466:    Input Parameters:
6467: +  mat - the matrix
6468: .  is - index set of rows to remove
6469: .  diag - value put in all diagonals of eliminated rows
6470: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6471: -  b - optional vector of right hand side, that will be adjusted by provided solution

6473:    Level: intermediate

6475:    Notes:
6476:    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6477:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6479:    See `MatZeroRowsColumns()` for details on how this routine operates.

6481: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6482:           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6483: @*/
6484: PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6485: {
6486:   PetscInt        numRows;
6487:   const PetscInt *rows;

6494:   MatCheckPreallocated(mat, 1);

6496:   ISGetLocalSize(is, &numRows);
6497:   ISGetIndices(is, &rows);
6498:   MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b);
6499:   ISRestoreIndices(is, &rows);
6500:   return 0;
6501: }

6503: /*@C
6504:    MatGetSize - Returns the numbers of rows and columns in a matrix.

6506:    Not Collective

6508:    Input Parameter:
6509: .  mat - the matrix

6511:    Level: beginner

6513:    Output Parameters:
6514: +  m - the number of global rows
6515: -  n - the number of global columns

6517:    Note:
6518:    Both output parameters can be `NULL` on input.

6520: .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6521: @*/
6522: PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6523: {
6525:   if (m) *m = mat->rmap->N;
6526:   if (n) *n = mat->cmap->N;
6527:   return 0;
6528: }

6530: /*@C
6531:    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6532:    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.

6534:    Not Collective

6536:    Input Parameter:
6537: .  mat - the matrix

6539:    Output Parameters:
6540: +  m - the number of local rows, use `NULL` to not obtain this value
6541: -  n - the number of local columns, use `NULL` to not obtain this value

6543:    Level: beginner

6545: .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6546: @*/
6547: PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6548: {
6552:   if (m) *m = mat->rmap->n;
6553:   if (n) *n = mat->cmap->n;
6554:   return 0;
6555: }

6557: /*@C
6558:    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6559:    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.

6561:    Not Collective, unless matrix has not been allocated, then collective

6563:    Input Parameter:
6564: .  mat - the matrix

6566:    Output Parameters:
6567: +  m - the global index of the first local column, use `NULL` to not obtain this value
6568: -  n - one more than the global index of the last local column, use `NULL` to not obtain this value

6570:    Level: developer

6572: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6573: @*/
6574: PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6575: {
6580:   MatCheckPreallocated(mat, 1);
6581:   if (m) *m = mat->cmap->rstart;
6582:   if (n) *n = mat->cmap->rend;
6583:   return 0;
6584: }

6586: /*@C
6587:    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6588:    this MPI rank. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6589:    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts

6591:    Not Collective

6593:    Input Parameter:
6594: .  mat - the matrix

6596:    Output Parameters:
6597: +  m - the global index of the first local row, use `NULL` to not obtain this value
6598: -  n - one more than the global index of the last local row, use `NULL` to not obtain this value

6600:    Level: beginner

6602:    Note:
6603:   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6604:   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6605:   and then `MPI_Scan()` to calculate prefix sums of the local sizes.

6607: .seealso: `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6608:           `PetscLayout`
6609: @*/
6610: PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6611: {
6616:   MatCheckPreallocated(mat, 1);
6617:   if (m) *m = mat->rmap->rstart;
6618:   if (n) *n = mat->rmap->rend;
6619:   return 0;
6620: }

6622: /*@C
6623:    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6624:    each process. For all matrices  it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix
6625:    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts

6627:    Not Collective, unless matrix has not been allocated, then collective

6629:    Input Parameters:
6630: .  mat - the matrix

6632:    Output Parameters:
6633: .  ranges - start of each processors portion plus one more than the total length at the end

6635:    Level: beginner

6637: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6638: @*/
6639: PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6640: {
6643:   MatCheckPreallocated(mat, 1);
6644:   PetscLayoutGetRanges(mat->rmap, ranges);
6645:   return 0;
6646: }

6648: /*@C
6649:    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6650:    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.

6652:    Not Collective, unless matrix has not been allocated, then collective on Mat

6654:    Input Parameters:
6655: .  mat - the matrix

6657:    Output Parameters:
6658: .  ranges - start of each processors portion plus one more then the total length at the end

6660:    Level: beginner

6662: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6663: @*/
6664: PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6665: {
6668:   MatCheckPreallocated(mat, 1);
6669:   PetscLayoutGetRanges(mat->cmap, ranges);
6670:   return 0;
6671: }

6673: /*@C
6674:    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6675:    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6676:    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.

6678:    Not Collective

6680:    Input Parameter:
6681: .  A - matrix

6683:    Output Parameters:
6684: +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6685: -  cols - columns in which this process owns elements, use `NULL` to not obtain this value

6687:    Level: intermediate

6689: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6690: @*/
6691: PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6692: {
6693:   PetscErrorCode (*f)(Mat, IS *, IS *);

6695:   MatCheckPreallocated(A, 1);
6696:   PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f);
6697:   if (f) {
6698:     (*f)(A, rows, cols);
6699:   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6700:     if (rows) ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows);
6701:     if (cols) ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols);
6702:   }
6703:   return 0;
6704: }

6706: /*@C
6707:    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6708:    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6709:    to complete the factorization.

6711:    Collective on fact

6713:    Input Parameters:
6714: +  fact - the factorized matrix obtained with `MatGetFactor()`
6715: .  mat - the matrix
6716: .  row - row permutation
6717: .  column - column permutation
6718: -  info - structure containing
6719: .vb
6720:       levels - number of levels of fill.
6721:       expected fill - as ratio of original fill.
6722:       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6723:                 missing diagonal entries)
6724: .ve

6726:    Output Parameters:
6727: .  fact - new matrix that has been symbolically factored

6729:    Level: developer

6731:    Notes:
6732:    See [Matrix Factorization](sec_matfactor) for additional information.

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

6738:    Uses the definition of level of fill as in Y. Saad, 2003

6740:    Developer Note:
6741:    The Fortran interface is not autogenerated as the
6742:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

6744:    References:
6745: .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003

6747: .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6748:           `MatGetOrdering()`, `MatFactorInfo`
6749: @*/
6750: PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6751: {
6760:   if (!fact->ops->ilufactorsymbolic) {
6761:     MatSolverType stype;
6762:     MatFactorGetSolverType(fact, &stype);
6763:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6764:   }
6767:   MatCheckPreallocated(mat, 2);

6769:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0);
6770:   (fact->ops->ilufactorsymbolic)(fact, mat, row, col, info);
6771:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0);
6772:   return 0;
6773: }

6775: /*@C
6776:    MatICCFactorSymbolic - Performs symbolic incomplete
6777:    Cholesky factorization for a symmetric matrix.  Use
6778:    `MatCholeskyFactorNumeric()` to complete the factorization.

6780:    Collective on fact

6782:    Input Parameters:
6783: +  fact - the factorized matrix obtained with `MatGetFactor()`
6784: .  mat - the matrix to be factored
6785: .  perm - row and column permutation
6786: -  info - structure containing
6787: .vb
6788:       levels - number of levels of fill.
6789:       expected fill - as ratio of original fill.
6790: .ve

6792:    Output Parameter:
6793: .  fact - the factored matrix

6795:    Level: developer

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

6802:    This uses the definition of level of fill as in Y. Saad, 2003

6804:    Developer Note:
6805:    The Fortran interface is not autogenerated as the
6806:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

6808:    References:
6809: .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003

6811: .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6812: @*/
6813: PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6814: {
6823:   if (!(fact)->ops->iccfactorsymbolic) {
6824:     MatSolverType stype;
6825:     MatFactorGetSolverType(fact, &stype);
6826:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6827:   }
6829:   MatCheckPreallocated(mat, 2);

6831:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6832:   (fact->ops->iccfactorsymbolic)(fact, mat, perm, info);
6833:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6834:   return 0;
6835: }

6837: /*@C
6838:    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6839:    points to an array of valid matrices, they may be reused to store the new
6840:    submatrices.

6842:    Collective

6844:    Input Parameters:
6845: +  mat - the matrix
6846: .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6847: .  irow, icol - index sets of rows and columns to extract
6848: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

6850:    Output Parameter:
6851: .  submat - the array of submatrices

6853:    Level: advanced

6855:    Notes:
6856:    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6857:    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6858:    to extract a parallel submatrix.

6860:    Some matrix types place restrictions on the row and column
6861:    indices, such as that they be sorted or that they be equal to each other.

6863:    The index sets may not have duplicate entries.

6865:    When extracting submatrices from a parallel matrix, each processor can
6866:    form a different submatrix by setting the rows and columns of its
6867:    individual index sets according to the local submatrix desired.

6869:    When finished using the submatrices, the user should destroy
6870:    them with `MatDestroySubMatrices()`.

6872:    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6873:    original matrix has not changed from that last call to `MatCreateSubMatrices()`.

6875:    This routine creates the matrices in submat; you should NOT create them before
6876:    calling it. It also allocates the array of matrix pointers submat.

6878:    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6879:    request one row/column in a block, they must request all rows/columns that are in
6880:    that block. For example, if the block size is 2 you cannot request just row 0 and
6881:    column 0.

6883:    Fortran Note:
6884:    The Fortran interface is slightly different from that given below; it
6885:    requires one to pass in  as submat a `Mat` (integer) array of size at least n+1.

6887: .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6888: @*/
6889: PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6890: {
6891:   PetscInt  i;
6892:   PetscBool eq;

6896:   if (n) {
6901:   }
6903:   if (n && scall == MAT_REUSE_MATRIX) {
6906:   }
6909:   MatCheckPreallocated(mat, 1);
6910:   PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6911:   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6912:   PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6913:   for (i = 0; i < n; i++) {
6914:     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6915:     ISEqualUnsorted(irow[i], icol[i], &eq);
6916:     if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6917: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
6918:     if (mat->boundtocpu && mat->bindingpropagates) {
6919:       MatBindToCPU((*submat)[i], PETSC_TRUE);
6920:       MatSetBindingPropagates((*submat)[i], PETSC_TRUE);
6921:     }
6922: #endif
6923:   }
6924:   return 0;
6925: }

6927: /*@C
6928:    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).

6930:    Collective

6932:    Input Parameters:
6933: +  mat - the matrix
6934: .  n   - the number of submatrixes to be extracted
6935: .  irow, icol - index sets of rows and columns to extract
6936: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

6938:    Output Parameter:
6939: .  submat - the array of submatrices

6941:    Level: advanced

6943:    Note:
6944:    This is used by `PCGASM`

6946: .seealso: `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6947: @*/
6948: PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6949: {
6950:   PetscInt  i;
6951:   PetscBool eq;

6955:   if (n) {
6960:   }
6962:   if (n && scall == MAT_REUSE_MATRIX) {
6965:   }
6968:   MatCheckPreallocated(mat, 1);

6970:   PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6971:   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6972:   PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6973:   for (i = 0; i < n; i++) {
6974:     ISEqualUnsorted(irow[i], icol[i], &eq);
6975:     if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6976:   }
6977:   return 0;
6978: }

6980: /*@C
6981:    MatDestroyMatrices - Destroys an array of matrices.

6983:    Collective

6985:    Input Parameters:
6986: +  n - the number of local matrices
6987: -  mat - the matrices (note that this is a pointer to the array of matrices)

6989:    Level: advanced

6991:     Note:
6992:     Frees not only the matrices, but also the array that contains the matrices

6994:     Fortran Note:
6995:     Will not free the array.

6997: .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6998: @*/
6999: PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7000: {
7001:   PetscInt i;

7003:   if (!*mat) return 0;

7007:   for (i = 0; i < n; i++) MatDestroy(&(*mat)[i]);

7009:   /* memory is allocated even if n = 0 */
7010:   PetscFree(*mat);
7011:   return 0;
7012: }

7014: /*@C
7015:    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.

7017:    Collective

7019:    Input Parameters:
7020: +  n - the number of local matrices
7021: -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7022:                        sequence of MatCreateSubMatrices())

7024:    Level: advanced

7026:     Note:
7027:     Frees not only the matrices, but also the array that contains the matrices

7029:     Fortran Note:
7030:     Will not free the array.

7032: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7033: @*/
7034: PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7035: {
7036:   Mat mat0;

7038:   if (!*mat) return 0;
7039:   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */

7043:   mat0 = (*mat)[0];
7044:   if (mat0 && mat0->ops->destroysubmatrices) {
7045:     (mat0->ops->destroysubmatrices)(n, mat);
7046:   } else {
7047:     MatDestroyMatrices(n, mat);
7048:   }
7049:   return 0;
7050: }

7052: /*@C
7053:    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process

7055:    Collective

7057:    Input Parameters:
7058: .  mat - the matrix

7060:    Output Parameter:
7061: .  matstruct - the sequential matrix with the nonzero structure of mat

7063:   Level: developer

7065: .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7066: @*/
7067: PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7068: {

7074:   MatCheckPreallocated(mat, 1);

7076:   PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7077:   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7078:   PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7079:   return 0;
7080: }

7082: /*@C
7083:    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.

7085:    Collective

7087:    Input Parameters:
7088: .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7089:                        sequence of `MatGetSequentialNonzeroStructure()`)

7091:    Level: advanced

7093:     Note:
7094:     Frees not only the matrices, but also the array that contains the matrices

7096: .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7097: @*/
7098: PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7099: {
7101:   MatDestroy(mat);
7102:   return 0;
7103: }

7105: /*@
7106:    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7107:    replaces the index sets by larger ones that represent submatrices with
7108:    additional overlap.

7110:    Collective

7112:    Input Parameters:
7113: +  mat - the matrix
7114: .  n   - the number of index sets
7115: .  is  - the array of index sets (these index sets will changed during the call)
7116: -  ov  - the additional overlap requested

7118:    Options Database Key:
7119: .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)

7121:    Level: developer

7123:    Note:
7124:    The computed overlap preserves the matrix block sizes when the blocks are square.
7125:    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7126:    that block are included in the overlap regardless of whether each specific column would increase the overlap.

7128: .seealso: `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7129: @*/
7130: PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7131: {
7132:   PetscInt i, bs, cbs;

7138:   if (n) {
7141:   }
7144:   MatCheckPreallocated(mat, 1);

7146:   if (!ov || !n) return 0;
7147:   PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7148:   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7149:   PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7150:   MatGetBlockSizes(mat, &bs, &cbs);
7151:   if (bs == cbs) {
7152:     for (i = 0; i < n; i++) ISSetBlockSize(is[i], bs);
7153:   }
7154:   return 0;
7155: }

7157: PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);

7159: /*@
7160:    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7161:    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7162:    additional overlap.

7164:    Collective

7166:    Input Parameters:
7167: +  mat - the matrix
7168: .  n   - the number of index sets
7169: .  is  - the array of index sets (these index sets will changed during the call)
7170: -  ov  - the additional overlap requested

7172: `   Options Database Key:
7173: .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)

7175:    Level: developer

7177: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7178: @*/
7179: PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7180: {
7181:   PetscInt i;

7186:   if (n) {
7189:   }
7192:   MatCheckPreallocated(mat, 1);
7193:   if (!ov) return 0;
7194:   PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7195:   for (i = 0; i < n; i++) MatIncreaseOverlapSplit_Single(mat, &is[i], ov);
7196:   PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7197:   return 0;
7198: }

7200: /*@
7201:    MatGetBlockSize - Returns the matrix block size.

7203:    Not Collective

7205:    Input Parameter:
7206: .  mat - the matrix

7208:    Output Parameter:
7209: .  bs - block size

7211:    Level: intermediate

7213:    Notes:
7214:     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.

7216:    If the block size has not been set yet this routine returns 1.

7218: .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7219: @*/
7220: PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7221: {
7224:   *bs = PetscAbs(mat->rmap->bs);
7225:   return 0;
7226: }

7228: /*@
7229:    MatGetBlockSizes - Returns the matrix block row and column sizes.

7231:    Not Collective

7233:    Input Parameter:
7234: .  mat - the matrix

7236:    Output Parameters:
7237: +  rbs - row block size
7238: -  cbs - column block size

7240:    Level: intermediate

7242:    Notes:
7243:     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7244:     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.

7246:    If a block size has not been set yet this routine returns 1.

7248: .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7249: @*/
7250: PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7251: {
7255:   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7256:   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7257:   return 0;
7258: }

7260: /*@
7261:    MatSetBlockSize - Sets the matrix block size.

7263:    Logically Collective

7265:    Input Parameters:
7266: +  mat - the matrix
7267: -  bs - block size

7269:    Level: intermediate

7271:    Notes:
7272:     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7273:     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.

7275:     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7276:     is compatible with the matrix local sizes.

7278: .seealso: `Mat`,  `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7279: @*/
7280: PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7281: {
7284:   MatSetBlockSizes(mat, bs, bs);
7285:   return 0;
7286: }

7288: typedef struct {
7289:   PetscInt         n;
7290:   IS              *is;
7291:   Mat             *mat;
7292:   PetscObjectState nonzerostate;
7293:   Mat              C;
7294: } EnvelopeData;

7296: static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7297: {
7298:   for (PetscInt i = 0; i < edata->n; i++) ISDestroy(&edata->is[i]);
7299:   PetscFree(edata->is);
7300:   PetscFree(edata);
7301:   return 0;
7302: }

7304: /*
7305:    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7306:          the sizes of these blocks in the matrix. An individual block may lie over several processes.

7308:    Collective

7310:    Input Parameter:
7311: .  mat - the matrix

7313:    Notes:
7314:      There can be zeros within the blocks

7316:      The blocks can overlap between processes, including laying on more than two processes

7318: .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7319: */
7320: static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7321: {
7322:   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7323:   PetscInt          *diag, *odiag, sc;
7324:   VecScatter         scatter;
7325:   PetscScalar       *seqv;
7326:   const PetscScalar *parv;
7327:   const PetscInt    *ia, *ja;
7328:   PetscBool          set, flag, done;
7329:   Mat                AA = mat, A;
7330:   MPI_Comm           comm;
7331:   PetscMPIInt        rank, size, tag;
7332:   MPI_Status         status;
7333:   PetscContainer     container;
7334:   EnvelopeData      *edata;
7335:   Vec                seq, par;
7336:   IS                 isglobal;

7339:   MatIsSymmetricKnown(mat, &set, &flag);
7340:   if (!set || !flag) {
7341:     /* TOO: only needs nonzero structure of transpose */
7342:     MatTranspose(mat, MAT_INITIAL_MATRIX, &AA);
7343:     MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN);
7344:   }
7345:   MatAIJGetLocalMat(AA, &A);
7346:   MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);

7349:   MatGetLocalSize(mat, &n, NULL);
7350:   PetscObjectGetNewTag((PetscObject)mat, &tag);
7351:   PetscObjectGetComm((PetscObject)mat, &comm);
7352:   MPI_Comm_size(comm, &size);
7353:   MPI_Comm_rank(comm, &rank);

7355:   PetscMalloc2(n, &sizes, n, &starts);

7357:   if (rank > 0) {
7358:     MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status);
7359:     MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status);
7360:   }
7361:   MatGetOwnershipRange(mat, &rstart, NULL);
7362:   for (i = 0; i < n; i++) {
7363:     env = PetscMax(env, ja[ia[i + 1] - 1]);
7364:     II  = rstart + i;
7365:     if (env == II) {
7366:       starts[lblocks]  = tbs;
7367:       sizes[lblocks++] = 1 + II - tbs;
7368:       tbs              = 1 + II;
7369:     }
7370:   }
7371:   if (rank < size - 1) {
7372:     MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm);
7373:     MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm);
7374:   }

7376:   MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7377:   if (!set || !flag) MatDestroy(&AA);
7378:   MatDestroy(&A);

7380:   PetscNew(&edata);
7381:   MatGetNonzeroState(mat, &edata->nonzerostate);
7382:   edata->n = lblocks;
7383:   /* create IS needed for extracting blocks from the original matrix */
7384:   PetscMalloc1(lblocks, &edata->is);
7385:   for (PetscInt i = 0; i < lblocks; i++) ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]);

7387:   /* Create the resulting inverse matrix structure with preallocation information */
7388:   MatCreate(PetscObjectComm((PetscObject)mat), &edata->C);
7389:   MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
7390:   MatSetBlockSizesFromMats(edata->C, mat, mat);
7391:   MatSetType(edata->C, MATAIJ);

7393:   /* Communicate the start and end of each row, from each block to the correct rank */
7394:   /* TODO: Use PetscSF instead of VecScatter */
7395:   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7396:   VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq);
7397:   VecGetArrayWrite(seq, &seqv);
7398:   for (PetscInt i = 0; i < lblocks; i++) {
7399:     for (PetscInt j = 0; j < sizes[i]; j++) {
7400:       seqv[cnt]     = starts[i];
7401:       seqv[cnt + 1] = starts[i] + sizes[i];
7402:       cnt += 2;
7403:     }
7404:   }
7405:   VecRestoreArrayWrite(seq, &seqv);
7406:   MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
7407:   sc -= cnt;
7408:   VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par);
7409:   ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal);
7410:   VecScatterCreate(seq, NULL, par, isglobal, &scatter);
7411:   ISDestroy(&isglobal);
7412:   VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7413:   VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7414:   VecScatterDestroy(&scatter);
7415:   VecDestroy(&seq);
7416:   MatGetOwnershipRangeColumn(mat, &cstart, &cend);
7417:   PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag);
7418:   VecGetArrayRead(par, &parv);
7419:   cnt = 0;
7420:   MatGetSize(mat, NULL, &n);
7421:   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7422:     PetscInt start, end, d = 0, od = 0;

7424:     start = (PetscInt)PetscRealPart(parv[cnt]);
7425:     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7426:     cnt += 2;

7428:     if (start < cstart) {
7429:       od += cstart - start + n - cend;
7430:       d += cend - cstart;
7431:     } else if (start < cend) {
7432:       od += n - cend;
7433:       d += cend - start;
7434:     } else od += n - start;
7435:     if (end <= cstart) {
7436:       od -= cstart - end + n - cend;
7437:       d -= cend - cstart;
7438:     } else if (end < cend) {
7439:       od -= n - cend;
7440:       d -= cend - end;
7441:     } else od -= n - end;

7443:     odiag[i] = od;
7444:     diag[i]  = d;
7445:   }
7446:   VecRestoreArrayRead(par, &parv);
7447:   VecDestroy(&par);
7448:   MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL);
7449:   PetscFree2(diag, odiag);
7450:   PetscFree2(sizes, starts);

7452:   PetscContainerCreate(PETSC_COMM_SELF, &container);
7453:   PetscContainerSetPointer(container, edata);
7454:   PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy);
7455:   PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container);
7456:   PetscObjectDereference((PetscObject)container);
7457:   return 0;
7458: }

7460: /*@
7461:   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A

7463:   Collective

7465:   Input Parameters:
7466: . A - the matrix

7468:   Output Parameters:
7469: . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.

7471:   Level: advanced

7473:   Note:
7474:      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.

7476: .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7477: @*/
7478: PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7479: {
7480:   PetscContainer   container;
7481:   EnvelopeData    *edata;
7482:   PetscObjectState nonzerostate;

7484:   PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7485:   if (!container) {
7486:     MatComputeVariableBlockEnvelope(A);
7487:     PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7488:   }
7489:   PetscContainerGetPointer(container, (void **)&edata);
7490:   MatGetNonzeroState(A, &nonzerostate);

7494:   MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat);
7495:   *C = edata->C;

7497:   for (PetscInt i = 0; i < edata->n; i++) {
7498:     Mat          D;
7499:     PetscScalar *dvalues;

7501:     MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D);
7502:     MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE);
7503:     MatSeqDenseInvert(D);
7504:     MatDenseGetArray(D, &dvalues);
7505:     MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES);
7506:     MatDestroy(&D);
7507:   }
7508:   MatDestroySubMatrices(edata->n, &edata->mat);
7509:   MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY);
7510:   MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY);
7511:   return 0;
7512: }

7514: /*@
7515:    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size

7517:    Logically Collective

7519:    Input Parameters:
7520: +  mat - the matrix
7521: .  nblocks - the number of blocks on this process, each block can only exist on a single process
7522: -  bsizes - the block sizes

7524:    Level: intermediate

7526:    Notes:
7527:     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices

7529:     Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks.

7531: .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7532:           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7533: @*/
7534: PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7535: {
7536:   PetscInt i, ncnt = 0, nlocal;

7540:   MatGetLocalSize(mat, &nlocal, NULL);
7541:   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7543:   PetscFree(mat->bsizes);
7544:   mat->nblocks = nblocks;
7545:   PetscMalloc1(nblocks, &mat->bsizes);
7546:   PetscArraycpy(mat->bsizes, bsizes, nblocks);
7547:   return 0;
7548: }

7550: /*@C
7551:    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size

7553:    Logically Collective; No Fortran Support

7555:    Input Parameter:
7556: .  mat - the matrix

7558:    Output Parameters:
7559: +  nblocks - the number of blocks on this process
7560: -  bsizes - the block sizes

7562:    Level: intermediate

7564: .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7565: @*/
7566: PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7567: {
7569:   *nblocks = mat->nblocks;
7570:   *bsizes  = mat->bsizes;
7571:   return 0;
7572: }

7574: /*@
7575:    MatSetBlockSizes - Sets the matrix block row and column sizes.

7577:    Logically Collective

7579:    Input Parameters:
7580: +  mat - the matrix
7581: .  rbs - row block size
7582: -  cbs - column block size

7584:    Level: intermediate

7586:    Notes:
7587:     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7588:     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7589:     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.

7591:     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7592:     are compatible with the matrix local sizes.

7594:     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.

7596: .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7597: @*/
7598: PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7599: {
7603:   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7604:   if (mat->rmap->refcnt) {
7605:     ISLocalToGlobalMapping l2g  = NULL;
7606:     PetscLayout            nmap = NULL;

7608:     PetscLayoutDuplicate(mat->rmap, &nmap);
7609:     if (mat->rmap->mapping) ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g);
7610:     PetscLayoutDestroy(&mat->rmap);
7611:     mat->rmap          = nmap;
7612:     mat->rmap->mapping = l2g;
7613:   }
7614:   if (mat->cmap->refcnt) {
7615:     ISLocalToGlobalMapping l2g  = NULL;
7616:     PetscLayout            nmap = NULL;

7618:     PetscLayoutDuplicate(mat->cmap, &nmap);
7619:     if (mat->cmap->mapping) ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g);
7620:     PetscLayoutDestroy(&mat->cmap);
7621:     mat->cmap          = nmap;
7622:     mat->cmap->mapping = l2g;
7623:   }
7624:   PetscLayoutSetBlockSize(mat->rmap, rbs);
7625:   PetscLayoutSetBlockSize(mat->cmap, cbs);
7626:   return 0;
7627: }

7629: /*@
7630:    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices

7632:    Logically Collective

7634:    Input Parameters:
7635: +  mat - the matrix
7636: .  fromRow - matrix from which to copy row block size
7637: -  fromCol - matrix from which to copy column block size (can be same as fromRow)

7639:    Level: developer

7641: .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7642: @*/
7643: PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7644: {
7648:   if (fromRow->rmap->bs > 0) PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs);
7649:   if (fromCol->cmap->bs > 0) PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs);
7650:   return 0;
7651: }

7653: /*@
7654:    MatResidual - Default routine to calculate the residual r = b - Ax

7656:    Collective

7658:    Input Parameters:
7659: +  mat - the matrix
7660: .  b   - the right-hand-side
7661: -  x   - the approximate solution

7663:    Output Parameter:
7664: .  r - location to store the residual

7666:    Level: developer

7668: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7669: @*/
7670: PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7671: {
7677:   MatCheckPreallocated(mat, 1);
7678:   PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0);
7679:   if (!mat->ops->residual) {
7680:     MatMult(mat, x, r);
7681:     VecAYPX(r, -1.0, b);
7682:   } else {
7683:     PetscUseTypeMethod(mat, residual, b, x, r);
7684:   }
7685:   PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0);
7686:   return 0;
7687: }

7689: /*@C
7690:     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix

7692:    Collective

7694:     Input Parameters:
7695: +   mat - the matrix
7696: .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7697: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7698: -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7699:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7700:                  always used.

7702:     Output Parameters:
7703: +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7704: .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix, use `NULL` if not needed
7705: .   ja - the column indices, use `NULL` if not needed
7706: -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7707:            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set

7709:     Level: developer

7711:     Notes:
7712:     You CANNOT change any of the ia[] or ja[] values.

7714:     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.

7716:     Fortran Notes:
7717:     In Fortran use
7718: .vb
7719:       PetscInt ia(1), ja(1)
7720:       PetscOffset iia, jja
7721:       call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7722:       ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7723: .ve
7724:      or
7725: .vb
7726:     PetscInt, pointer :: ia(:),ja(:)
7727:     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7728:     ! Access the ith and jth entries via ia(i) and ja(j)
7729: .ve

7731: .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7732: @*/
7733: PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7734: {
7741:   MatCheckPreallocated(mat, 1);
7742:   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7743:   else {
7744:     if (done) *done = PETSC_TRUE;
7745:     PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0);
7746:     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7747:     PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0);
7748:   }
7749:   return 0;
7750: }

7752: /*@C
7753:     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.

7755:     Collective

7757:     Input Parameters:
7758: +   mat - the matrix
7759: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7760: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7761:                 symmetrized
7762: .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7763:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7764:                  always used.
7765: .   n - number of columns in the (possibly compressed) matrix
7766: .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7767: -   ja - the row indices

7769:     Output Parameters:
7770: .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned

7772:     Level: developer

7774: .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7775: @*/
7776: PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7777: {
7784:   MatCheckPreallocated(mat, 1);
7785:   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7786:   else {
7787:     *done = PETSC_TRUE;
7788:     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7789:   }
7790:   return 0;
7791: }

7793: /*@C
7794:     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.

7796:     Collective

7798:     Input Parameters:
7799: +   mat - the matrix
7800: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7801: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7802: .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7803:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7804:                  always used.
7805: .   n - size of (possibly compressed) matrix
7806: .   ia - the row pointers
7807: -   ja - the column indices

7809:     Output Parameters:
7810: .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned

7812:     Level: developer

7814:     Note:
7815:     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
7816:     us of the array after it has been restored. If you pass `NULL`, it will
7817:     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.

7819: .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7820: @*/
7821: PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7822: {
7828:   MatCheckPreallocated(mat, 1);

7830:   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7831:   else {
7832:     if (done) *done = PETSC_TRUE;
7833:     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7834:     if (n) *n = 0;
7835:     if (ia) *ia = NULL;
7836:     if (ja) *ja = NULL;
7837:   }
7838:   return 0;
7839: }

7841: /*@C
7842:     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.

7844:     Collective on Mat

7846:     Input Parameters:
7847: +   mat - the matrix
7848: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7849: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7850: -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7851:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7852:                  always used.

7854:     Output Parameters:
7855: +   n - size of (possibly compressed) matrix
7856: .   ia - the column pointers
7857: .   ja - the row indices
7858: -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned

7860:     Level: developer

7862: .seealso: `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7863: @*/
7864: PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7865: {
7871:   MatCheckPreallocated(mat, 1);

7873:   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7874:   else {
7875:     *done = PETSC_TRUE;
7876:     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7877:     if (n) *n = 0;
7878:     if (ia) *ia = NULL;
7879:     if (ja) *ja = NULL;
7880:   }
7881:   return 0;
7882: }

7884: /*@C
7885:     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.

7887:     Collective

7889:     Input Parameters:
7890: +   mat - the matrix
7891: .   ncolors - max color value
7892: .   n   - number of entries in colorarray
7893: -   colorarray - array indicating color for each column

7895:     Output Parameters:
7896: .   iscoloring - coloring generated using colorarray information

7898:     Level: developer

7900: .seealso: `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
7901: @*/
7902: PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
7903: {
7908:   MatCheckPreallocated(mat, 1);

7910:   if (!mat->ops->coloringpatch) {
7911:     ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring);
7912:   } else {
7913:     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7914:   }
7915:   return 0;
7916: }

7918: /*@
7919:    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.

7921:    Logically Collective

7923:    Input Parameter:
7924: .  mat - the factored matrix to be reset

7926:    Level: developer

7928:    Notes:
7929:    This routine should be used only with factored matrices formed by in-place
7930:    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
7931:    format).  This option can save memory, for example, when solving nonlinear
7932:    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7933:    ILU(0) preconditioner.

7935:    Note that one can specify in-place ILU(0) factorization by calling
7936: .vb
7937:      PCType(pc,PCILU);
7938:      PCFactorSeUseInPlace(pc);
7939: .ve
7940:    or by using the options -pc_type ilu -pc_factor_in_place

7942:    In-place factorization ILU(0) can also be used as a local
7943:    solver for the blocks within the block Jacobi or additive Schwarz
7944:    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
7945:    for details on setting local solver options.

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

7951: .seealso: `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7952: @*/
7953: PetscErrorCode MatSetUnfactored(Mat mat)
7954: {
7957:   MatCheckPreallocated(mat, 1);
7958:   mat->factortype = MAT_FACTOR_NONE;
7959:   if (!mat->ops->setunfactored) return 0;
7960:   PetscUseTypeMethod(mat, setunfactored);
7961:   return 0;
7962: }

7964: /*MC
7965:     MatDenseGetArrayF90 - Accesses a matrix array from Fortran

7967:     Synopsis:
7968:     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)

7970:     Not collective

7972:     Input Parameter:
7973: .   x - matrix

7975:     Output Parameters:
7976: +   xx_v - the Fortran pointer to the array
7977: -   ierr - error code

7979:     Example of Usage:
7980: .vb
7981:       PetscScalar, pointer xx_v(:,:)
7982:       ....
7983:       call MatDenseGetArrayF90(x,xx_v,ierr)
7984:       a = xx_v(3)
7985:       call MatDenseRestoreArrayF90(x,xx_v,ierr)
7986: .ve

7988:     Level: advanced

7990: .seealso: `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
7991: M*/

7993: /*MC
7994:     MatDenseRestoreArrayF90 - Restores a matrix array that has been
7995:     accessed with `MatDenseGetArrayF90()`.

7997:     Synopsis:
7998:     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)

8000:     Not collective

8002:     Input Parameters:
8003: +   x - matrix
8004: -   xx_v - the Fortran90 pointer to the array

8006:     Output Parameter:
8007: .   ierr - error code

8009:     Example of Usage:
8010: .vb
8011:        PetscScalar, pointer xx_v(:,:)
8012:        ....
8013:        call MatDenseGetArrayF90(x,xx_v,ierr)
8014:        a = xx_v(3)
8015:        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8016: .ve

8018:     Level: advanced

8020: .seealso: `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8021: M*/

8023: /*MC
8024:     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.

8026:     Synopsis:
8027:     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)

8029:     Not collective

8031:     Input Parameter:
8032: .   x - matrix

8034:     Output Parameters:
8035: +   xx_v - the Fortran pointer to the array
8036: -   ierr - error code

8038:     Example of Usage:
8039: .vb
8040:       PetscScalar, pointer xx_v(:)
8041:       ....
8042:       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8043:       a = xx_v(3)
8044:       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8045: .ve

8047:     Level: advanced

8049: .seealso: `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8050: M*/

8052: /*MC
8053:     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8054:     accessed with `MatSeqAIJGetArrayF90()`.

8056:     Synopsis:
8057:     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)

8059:     Not collective

8061:     Input Parameters:
8062: +   x - matrix
8063: -   xx_v - the Fortran90 pointer to the array

8065:     Output Parameter:
8066: .   ierr - error code

8068:     Example of Usage:
8069: .vb
8070:        PetscScalar, pointer xx_v(:)
8071:        ....
8072:        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8073:        a = xx_v(3)
8074:        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8075: .ve

8077:     Level: advanced

8079: .seealso: `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8080: M*/

8082: /*@
8083:     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8084:                       as the original matrix.

8086:     Collective

8088:     Input Parameters:
8089: +   mat - the original matrix
8090: .   isrow - parallel IS containing the rows this processor should obtain
8091: .   iscol - parallel IS containing all columns you wish to keep. Each process should list the columns that will be in IT's "diagonal part" in the new matrix.
8092: -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

8094:     Output Parameter:
8095: .   newmat - the new submatrix, of the same type as the old

8097:     Level: advanced

8099:     Notes:
8100:     The submatrix will be able to be multiplied with vectors using the same layout as iscol.

8102:     Some matrix types place restrictions on the row and column indices, such
8103:     as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block;
8104:     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.

8106:     The index sets may not have duplicate entries.

8108:       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8109:    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8110:    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8111:    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8112:    you are finished using it.

8114:     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8115:     the input matrix.

8117:     If iscol is `NULL` then all columns are obtained (not supported in Fortran).

8119:    Example usage:
8120:    Consider the following 8x8 matrix with 34 non-zero values, that is
8121:    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8122:    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8123:    as follows:

8125: .vb
8126:             1  2  0  |  0  3  0  |  0  4
8127:     Proc0   0  5  6  |  7  0  0  |  8  0
8128:             9  0 10  | 11  0  0  | 12  0
8129:     -------------------------------------
8130:            13  0 14  | 15 16 17  |  0  0
8131:     Proc1   0 18  0  | 19 20 21  |  0  0
8132:             0  0  0  | 22 23  0  | 24  0
8133:     -------------------------------------
8134:     Proc2  25 26 27  |  0  0 28  | 29  0
8135:            30  0  0  | 31 32 33  |  0 34
8136: .ve

8138:     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is

8140: .vb
8141:             2  0  |  0  3  0  |  0
8142:     Proc0   5  6  |  7  0  0  |  8
8143:     -------------------------------
8144:     Proc1  18  0  | 19 20 21  |  0
8145:     -------------------------------
8146:     Proc2  26 27  |  0  0 28  | 29
8147:             0  0  | 31 32 33  |  0
8148: .ve

8150: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8151: @*/
8152: PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8153: {
8154:   PetscMPIInt size;
8155:   Mat        *local;
8156:   IS          iscoltmp;
8157:   PetscBool   flg;


8168:   MatCheckPreallocated(mat, 1);
8169:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);

8171:   if (!iscol || isrow == iscol) {
8172:     PetscBool   stride;
8173:     PetscMPIInt grabentirematrix = 0, grab;
8174:     PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride);
8175:     if (stride) {
8176:       PetscInt first, step, n, rstart, rend;
8177:       ISStrideGetInfo(isrow, &first, &step);
8178:       if (step == 1) {
8179:         MatGetOwnershipRange(mat, &rstart, &rend);
8180:         if (rstart == first) {
8181:           ISGetLocalSize(isrow, &n);
8182:           if (n == rend - rstart) grabentirematrix = 1;
8183:         }
8184:       }
8185:     }
8186:     MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat));
8187:     if (grab) {
8188:       PetscInfo(mat, "Getting entire matrix as submatrix\n");
8189:       if (cll == MAT_INITIAL_MATRIX) {
8190:         *newmat = mat;
8191:         PetscObjectReference((PetscObject)mat);
8192:       }
8193:       return 0;
8194:     }
8195:   }

8197:   if (!iscol) {
8198:     ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp);
8199:   } else {
8200:     iscoltmp = iscol;
8201:   }

8203:   /* if original matrix is on just one processor then use submatrix generated */
8204:   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8205:     MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat);
8206:     goto setproperties;
8207:   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8208:     MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local);
8209:     *newmat = *local;
8210:     PetscFree(local);
8211:     goto setproperties;
8212:   } else if (!mat->ops->createsubmatrix) {
8213:     /* Create a new matrix type that implements the operation using the full matrix */
8214:     PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8215:     switch (cll) {
8216:     case MAT_INITIAL_MATRIX:
8217:       MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat);
8218:       break;
8219:     case MAT_REUSE_MATRIX:
8220:       MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp);
8221:       break;
8222:     default:
8223:       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8224:     }
8225:     PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8226:     goto setproperties;
8227:   }

8229:   PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8230:   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8231:   PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);

8233: setproperties:
8234:   ISEqualUnsorted(isrow, iscoltmp, &flg);
8235:   if (flg) MatPropagateSymmetryOptions(mat, *newmat);
8236:   if (!iscol) ISDestroy(&iscoltmp);
8237:   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscObjectStateIncrease((PetscObject)*newmat);
8238:   return 0;
8239: }

8241: /*@
8242:    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix

8244:    Not Collective

8246:    Input Parameters:
8247: +  A - the matrix we wish to propagate options from
8248: -  B - the matrix we wish to propagate options to

8250:    Level: beginner

8252:    Note:
8253:    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`

8255: .seealso: `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8256: @*/
8257: PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8258: {
8261:   B->symmetry_eternal            = A->symmetry_eternal;
8262:   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8263:   B->symmetric                   = A->symmetric;
8264:   B->structurally_symmetric      = A->structurally_symmetric;
8265:   B->spd                         = A->spd;
8266:   B->hermitian                   = A->hermitian;
8267:   return 0;
8268: }

8270: /*@
8271:    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8272:    used during the assembly process to store values that belong to
8273:    other processors.

8275:    Not Collective

8277:    Input Parameters:
8278: +  mat   - the matrix
8279: .  size  - the initial size of the stash.
8280: -  bsize - the initial size of the block-stash(if used).

8282:    Options Database Keys:
8283: +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8284: -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>

8286:    Level: intermediate

8288:    Notes:
8289:      The block-stash is used for values set with `MatSetValuesBlocked()` while
8290:      the stash is used for values set with `MatSetValues()`

8292:      Run with the option -info and look for output of the form
8293:      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8294:      to determine the appropriate value, MM, to use for size and
8295:      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8296:      to determine the value, BMM to use for bsize

8298: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8299: @*/
8300: PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8301: {
8304:   MatStashSetInitialSize_Private(&mat->stash, size);
8305:   MatStashSetInitialSize_Private(&mat->bstash, bsize);
8306:   return 0;
8307: }

8309: /*@
8310:    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8311:      the matrix

8313:    Neighbor-wise Collective

8315:    Input Parameters:
8316: +  mat   - the matrix
8317: .  x,y - the vectors
8318: -  w - where the result is stored

8320:    Level: intermediate

8322:    Notes:
8323:     `w` may be the same vector as `y`.

8325:     This allows one to use either the restriction or interpolation (its transpose)
8326:     matrix to do the interpolation

8328: .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8329: @*/
8330: PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8331: {
8332:   PetscInt M, N, Ny;

8338:   MatGetSize(A, &M, &N);
8339:   VecGetSize(y, &Ny);
8340:   if (M == Ny) {
8341:     MatMultAdd(A, x, y, w);
8342:   } else {
8343:     MatMultTransposeAdd(A, x, y, w);
8344:   }
8345:   return 0;
8346: }

8348: /*@
8349:    MatInterpolate - y = A*x or A'*x depending on the shape of
8350:      the matrix

8352:    Neighbor-wise Collective

8354:    Input Parameters:
8355: +  mat   - the matrix
8356: -  x,y - the vectors

8358:    Level: intermediate

8360:    Note:
8361:     This allows one to use either the restriction or interpolation (its transpose)
8362:     matrix to do the interpolation

8364: .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8365: @*/
8366: PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8367: {
8368:   PetscInt M, N, Ny;

8373:   MatGetSize(A, &M, &N);
8374:   VecGetSize(y, &Ny);
8375:   if (M == Ny) {
8376:     MatMult(A, x, y);
8377:   } else {
8378:     MatMultTranspose(A, x, y);
8379:   }
8380:   return 0;
8381: }

8383: /*@
8384:    MatRestrict - y = A*x or A'*x

8386:    Neighbor-wise Collective on Mat

8388:    Input Parameters:
8389: +  mat   - the matrix
8390: -  x,y - the vectors

8392:    Level: intermediate

8394:    Note:
8395:     This allows one to use either the restriction or interpolation (its transpose)
8396:     matrix to do the restriction

8398: .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8399: @*/
8400: PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8401: {
8402:   PetscInt M, N, Ny;

8407:   MatGetSize(A, &M, &N);
8408:   VecGetSize(y, &Ny);
8409:   if (M == Ny) {
8410:     MatMult(A, x, y);
8411:   } else {
8412:     MatMultTranspose(A, x, y);
8413:   }
8414:   return 0;
8415: }

8417: /*@
8418:    MatMatInterpolateAdd - Y = W + A*X or W + A'*X

8420:    Neighbor-wise Collective on Mat

8422:    Input Parameters:
8423: +  mat   - the matrix
8424: -  w, x - the input dense matrices

8426:    Output Parameters:
8427: .  y - the output dense matrix

8429:    Level: intermediate

8431:    Note:
8432:     This allows one to use either the restriction or interpolation (its transpose)
8433:     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8434:     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.

8436: .seealso: `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8437: @*/
8438: PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8439: {
8440:   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8441:   PetscBool trans = PETSC_TRUE;
8442:   MatReuse  reuse = MAT_INITIAL_MATRIX;

8449:   MatGetSize(A, &M, &N);
8450:   MatGetSize(x, &Mx, &Nx);
8451:   if (N == Mx) trans = PETSC_FALSE;
8453:   Mo = trans ? N : M;
8454:   if (*y) {
8455:     MatGetSize(*y, &My, &Ny);
8456:     if (Mo == My && Nx == Ny) {
8457:       reuse = MAT_REUSE_MATRIX;
8458:     } else {
8460:       MatDestroy(y);
8461:     }
8462:   }

8464:   if (w && *y == w) { /* this is to minimize changes in PCMG */
8465:     PetscBool flg;

8467:     PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w);
8468:     if (w) {
8469:       PetscInt My, Ny, Mw, Nw;

8471:       PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg);
8472:       MatGetSize(*y, &My, &Ny);
8473:       MatGetSize(w, &Mw, &Nw);
8474:       if (!flg || My != Mw || Ny != Nw) w = NULL;
8475:     }
8476:     if (!w) {
8477:       MatDuplicate(*y, MAT_COPY_VALUES, &w);
8478:       PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w);
8479:       PetscObjectDereference((PetscObject)w);
8480:     } else {
8481:       MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN);
8482:     }
8483:   }
8484:   if (!trans) {
8485:     MatMatMult(A, x, reuse, PETSC_DEFAULT, y);
8486:   } else {
8487:     MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y);
8488:   }
8489:   if (w) MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN);
8490:   return 0;
8491: }

8493: /*@
8494:    MatMatInterpolate - Y = A*X or A'*X

8496:    Neighbor-wise Collective on Mat

8498:    Input Parameters:
8499: +  mat   - the matrix
8500: -  x - the input dense matrix

8502:    Output Parameters:
8503: .  y - the output dense matrix

8505:    Level: intermediate

8507:    Note:
8508:     This allows one to use either the restriction or interpolation (its transpose)
8509:     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8510:     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.

8512: .seealso: `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8513: @*/
8514: PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8515: {
8516:   MatMatInterpolateAdd(A, x, NULL, y);
8517:   return 0;
8518: }

8520: /*@
8521:    MatMatRestrict - Y = A*X or A'*X

8523:    Neighbor-wise Collective on Mat

8525:    Input Parameters:
8526: +  mat   - the matrix
8527: -  x - the input dense matrix

8529:    Output Parameters:
8530: .  y - the output dense matrix

8532:    Level: intermediate

8534:    Note:
8535:     This allows one to use either the restriction or interpolation (its transpose)
8536:     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8537:     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.

8539: .seealso: `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8540: @*/
8541: PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8542: {
8543:   MatMatInterpolateAdd(A, x, NULL, y);
8544:   return 0;
8545: }

8547: /*@
8548:    MatGetNullSpace - retrieves the null space of a matrix.

8550:    Logically Collective

8552:    Input Parameters:
8553: +  mat - the matrix
8554: -  nullsp - the null space object

8556:    Level: developer

8558: .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8559: @*/
8560: PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8561: {
8564:   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8565:   return 0;
8566: }

8568: /*@
8569:    MatSetNullSpace - attaches a null space to a matrix.

8571:    Logically Collective

8573:    Input Parameters:
8574: +  mat - the matrix
8575: -  nullsp - the null space object

8577:    Level: advanced

8579:    Notes:
8580:       This null space is used by the `KSP` linear solvers to solve singular systems.

8582:       Overwrites any previous null space that may have been attached. You can remove the null space from the matrix object by calling this routine with an nullsp of `NULL`

8584:       For inconsistent singular systems (linear systems where the right hand side is not in the range of the operator) the `KSP` residuals will not converge to
8585:       to zero but the linear system will still be solved in a least squares sense.

8587:       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8588:    the domain of a matrix A (from R^n to R^m (m rows, n columns) R^n = the direct sum of the null space of A, n(A), + the range of A^T, R(A^T).
8589:    Similarly R^m = direct sum n(A^T) + R(A).  Hence the linear system A x = b has a solution only if b in R(A) (or correspondingly b is orthogonal to
8590:    n(A^T)) and if x is a solution then x + alpha n(A) is a solution for any alpha. The minimum norm solution is orthogonal to n(A). For problems without a solution
8591:    the solution that minimizes the norm of the residual (the least squares solution) can be obtained by solving A x = \hat{b} where \hat{b} is b orthogonalized to the n(A^T).
8592:    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.

8594:     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8595:     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8596:     routine also automatically calls `MatSetTransposeNullSpace()`.

8598:     The user should call `MatNullSpaceDestroy()`.

8600: .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8601:           `KSPSetPCSide()`
8602: @*/
8603: PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8604: {
8607:   if (nullsp) PetscObjectReference((PetscObject)nullsp);
8608:   MatNullSpaceDestroy(&mat->nullsp);
8609:   mat->nullsp = nullsp;
8610:   if (mat->symmetric == PETSC_BOOL3_TRUE) MatSetTransposeNullSpace(mat, nullsp);
8611:   return 0;
8612: }

8614: /*@
8615:    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.

8617:    Logically Collective

8619:    Input Parameters:
8620: +  mat - the matrix
8621: -  nullsp - the null space object

8623:    Level: developer

8625: .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8626: @*/
8627: PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8628: {
8632:   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8633:   return 0;
8634: }

8636: /*@
8637:    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix

8639:    Logically Collective

8641:    Input Parameters:
8642: +  mat - the matrix
8643: -  nullsp - the null space object

8645:    Level: advanced

8647:    Notes:
8648:    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.

8650:    See `MatSetNullSpace()`

8652: .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8653: @*/
8654: PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8655: {
8658:   if (nullsp) PetscObjectReference((PetscObject)nullsp);
8659:   MatNullSpaceDestroy(&mat->transnullsp);
8660:   mat->transnullsp = nullsp;
8661:   return 0;
8662: }

8664: /*@
8665:    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8666:         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.

8668:    Logically Collective

8670:    Input Parameters:
8671: +  mat - the matrix
8672: -  nullsp - the null space object

8674:    Level: advanced

8676:    Notes:
8677:    Overwrites any previous near null space that may have been attached

8679:    You can remove the null space by calling this routine with an nullsp of `NULL`

8681: .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8682: @*/
8683: PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8684: {
8688:   MatCheckPreallocated(mat, 1);
8689:   if (nullsp) PetscObjectReference((PetscObject)nullsp);
8690:   MatNullSpaceDestroy(&mat->nearnullsp);
8691:   mat->nearnullsp = nullsp;
8692:   return 0;
8693: }

8695: /*@
8696:    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`

8698:    Not Collective

8700:    Input Parameter:
8701: .  mat - the matrix

8703:    Output Parameter:
8704: .  nullsp - the null space object, `NULL` if not set

8706:    Level: advanced

8708: .seealso: `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8709: @*/
8710: PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8711: {
8715:   MatCheckPreallocated(mat, 1);
8716:   *nullsp = mat->nearnullsp;
8717:   return 0;
8718: }

8720: /*@C
8721:    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.

8723:    Collective

8725:    Input Parameters:
8726: +  mat - the matrix
8727: .  row - row/column permutation
8728: .  fill - expected fill factor >= 1.0
8729: -  level - level of fill, for ICC(k)

8731:    Notes:
8732:    Probably really in-place only when level of fill is zero, otherwise allocates
8733:    new space to store factored matrix and deletes previous memory.

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

8739:    Level: developer

8741:    Developer Note:
8742:    The Fortran interface is not autogenerated as the
8743:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

8745: .seealso: `Mat`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8746: @*/
8747: PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8748: {
8756:   MatCheckPreallocated(mat, 1);
8757:   PetscUseTypeMethod(mat, iccfactor, row, info);
8758:   PetscObjectStateIncrease((PetscObject)mat);
8759:   return 0;
8760: }

8762: /*@
8763:    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8764:          ghosted ones.

8766:    Not Collective

8768:    Input Parameters:
8769: +  mat - the matrix
8770: -  diag - the diagonal values, including ghost ones

8772:    Level: developer

8774:    Notes:
8775:     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices

8777:     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`

8779: .seealso: `Mat`, `MatDiagonalScale()`
8780: @*/
8781: PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8782: {
8783:   PetscMPIInt size;


8790:   PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
8791:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8792:   if (size == 1) {
8793:     PetscInt n, m;
8794:     VecGetSize(diag, &n);
8795:     MatGetSize(mat, NULL, &m);
8796:     if (m == n) {
8797:       MatDiagonalScale(mat, NULL, diag);
8798:     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8799:   } else {
8800:     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8801:   }
8802:   PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
8803:   PetscObjectStateIncrease((PetscObject)mat);
8804:   return 0;
8805: }

8807: /*@
8808:    MatGetInertia - Gets the inertia from a factored matrix

8810:    Collective

8812:    Input Parameter:
8813: .  mat - the matrix

8815:    Output Parameters:
8816: +   nneg - number of negative eigenvalues
8817: .   nzero - number of zero eigenvalues
8818: -   npos - number of positive eigenvalues

8820:    Level: advanced

8822:    Note:
8823:     Matrix must have been factored by `MatCholeskyFactor()`

8825: .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
8826: @*/
8827: PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8828: {
8833:   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8834:   return 0;
8835: }

8837: /*@C
8838:    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors

8840:    Neighbor-wise Collective

8842:    Input Parameters:
8843: +  mat - the factored matrix obtained with `MatGetFactor()`
8844: -  b - the right-hand-side vectors

8846:    Output Parameter:
8847: .  x - the result vectors

8849:    Level: developer

8851:    Note:
8852:    The vectors `b` and `x` cannot be the same.  I.e., one cannot
8853:    call `MatSolves`(A,x,x).

8855: .seealso: `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8856: @*/
8857: PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
8858: {
8863:   if (!mat->rmap->N && !mat->cmap->N) return 0;

8865:   MatCheckPreallocated(mat, 1);
8866:   PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0);
8867:   PetscUseTypeMethod(mat, solves, b, x);
8868:   PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0);
8869:   return 0;
8870: }

8872: /*@
8873:    MatIsSymmetric - Test whether a matrix is symmetric

8875:    Collective

8877:    Input Parameters:
8878: +  A - the matrix to test
8879: -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)

8881:    Output Parameters:
8882: .  flg - the result

8884:    Level: intermediate

8886:    Notes:
8887:     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results

8889:     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`

8891:     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8892:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

8894: .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
8895:           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8896: @*/
8897: PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
8898: {

8902:   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8903:   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8904:   else {
8905:     if (!A->ops->issymmetric) {
8906:       MatType mattype;
8907:       MatGetType(A, &mattype);
8908:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8909:     }
8910:     PetscUseTypeMethod(A, issymmetric, tol, flg);
8911:     if (!tol) MatSetOption(A, MAT_SYMMETRIC, *flg);
8912:   }
8913:   return 0;
8914: }

8916: /*@
8917:    MatIsHermitian - Test whether a matrix is Hermitian

8919:    Collective on Mat

8921:    Input Parameters:
8922: +  A - the matrix to test
8923: -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)

8925:    Output Parameters:
8926: .  flg - the result

8928:    Level: intermediate

8930:    Notes:
8931:     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results

8933:     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`

8935:     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8936:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)

8938: .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8939:           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8940: @*/
8941: PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
8942: {

8946:   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8947:   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8948:   else {
8949:     if (!A->ops->ishermitian) {
8950:       MatType mattype;
8951:       MatGetType(A, &mattype);
8952:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8953:     }
8954:     PetscUseTypeMethod(A, ishermitian, tol, flg);
8955:     if (!tol) MatSetOption(A, MAT_HERMITIAN, *flg);
8956:   }
8957:   return 0;
8958: }

8960: /*@
8961:    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state

8963:    Not Collective

8965:    Input Parameter:
8966: .  A - the matrix to check

8968:    Output Parameters:
8969: +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
8970: -  flg - the result (only valid if set is `PETSC_TRUE`)

8972:    Level: advanced

8974:    Notes:
8975:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
8976:    if you want it explicitly checked

8978:     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8979:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

8981: .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8982: @*/
8983: PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
8984: {
8988:   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8989:     *set = PETSC_TRUE;
8990:     *flg = PetscBool3ToBool(A->symmetric);
8991:   } else {
8992:     *set = PETSC_FALSE;
8993:   }
8994:   return 0;
8995: }

8997: /*@
8998:    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state

9000:    Not Collective

9002:    Input Parameter:
9003: .  A - the matrix to check

9005:    Output Parameters:
9006: +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9007: -  flg - the result (only valid if set is `PETSC_TRUE`)

9009:    Level: advanced

9011:    Notes:
9012:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).

9014:    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9015:    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)

9017: .seealso: `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9018: @*/
9019: PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9020: {
9024:   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9025:     *set = PETSC_TRUE;
9026:     *flg = PetscBool3ToBool(A->spd);
9027:   } else {
9028:     *set = PETSC_FALSE;
9029:   }
9030:   return 0;
9031: }

9033: /*@
9034:    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state

9036:    Not Collective

9038:    Input Parameter:
9039: .  A - the matrix to check

9041:    Output Parameters:
9042: +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9043: -  flg - the result (only valid if set is `PETSC_TRUE`)

9045:    Level: advanced

9047:    Notes:
9048:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9049:    if you want it explicitly checked

9051:    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9052:    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9054: .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9055: @*/
9056: PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9057: {
9061:   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9062:     *set = PETSC_TRUE;
9063:     *flg = PetscBool3ToBool(A->hermitian);
9064:   } else {
9065:     *set = PETSC_FALSE;
9066:   }
9067:   return 0;
9068: }

9070: /*@
9071:    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric

9073:    Collective on Mat

9075:    Input Parameter:
9076: .  A - the matrix to test

9078:    Output Parameters:
9079: .  flg - the result

9081:    Level: intermediate

9083:    Notes:
9084:    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`

9086:    One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9087:    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9089: .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9090: @*/
9091: PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9092: {
9095:   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9096:     *flg = PetscBool3ToBool(A->structurally_symmetric);
9097:   } else {
9098:     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9099:     MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg);
9100:   }
9101:   return 0;
9102: }

9104: /*@
9105:    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state

9107:    Not Collective

9109:    Input Parameter:
9110: .  A - the matrix to check

9112:    Output Parameters:
9113: +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9114: -  flg - the result (only valid if set is PETSC_TRUE)

9116:    Level: advanced

9118:    Notes:
9119:    One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9120:    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9122:    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)

9124: .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9125: @*/
9126: PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9127: {
9131:   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9132:     *set = PETSC_TRUE;
9133:     *flg = PetscBool3ToBool(A->structurally_symmetric);
9134:   } else {
9135:     *set = PETSC_FALSE;
9136:   }
9137:   return 0;
9138: }

9140: /*@
9141:    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9142:        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process

9144:     Not collective

9146:    Input Parameter:
9147: .   mat - the matrix

9149:    Output Parameters:
9150: +   nstash   - the size of the stash
9151: .   reallocs - the number of additional mallocs incurred.
9152: .   bnstash   - the size of the block stash
9153: -   breallocs - the number of additional mallocs incurred.in the block stash

9155:    Level: advanced

9157: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9158: @*/
9159: PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9160: {
9161:   MatStashGetInfo_Private(&mat->stash, nstash, reallocs);
9162:   MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs);
9163:   return 0;
9164: }

9166: /*@C
9167:    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9168:    parallel layout, `PetscLayout` for rows and columns

9170:    Collective

9172:    Input Parameter:
9173: .  mat - the matrix

9175:    Output Parameters:
9176: +   right - (optional) vector that the matrix can be multiplied against
9177: -   left - (optional) vector that the matrix vector product can be stored in

9179:   Level: advanced

9181:    Notes:
9182:     The blocksize of the returned vectors is determined by the row and column block sizes set with `MatSetBlockSizes()` or the single blocksize (same for both) set by `MatSetBlockSize()`.

9184:     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed

9186: .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9187: @*/
9188: PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9189: {
9192:   if (mat->ops->getvecs) {
9193:     PetscUseTypeMethod(mat, getvecs, right, left);
9194:   } else {
9195:     PetscInt rbs, cbs;
9196:     MatGetBlockSizes(mat, &rbs, &cbs);
9197:     if (right) {
9199:       VecCreate(PetscObjectComm((PetscObject)mat), right);
9200:       VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE);
9201:       VecSetBlockSize(*right, cbs);
9202:       VecSetType(*right, mat->defaultvectype);
9203: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9204:       if (mat->boundtocpu && mat->bindingpropagates) {
9205:         VecSetBindingPropagates(*right, PETSC_TRUE);
9206:         VecBindToCPU(*right, PETSC_TRUE);
9207:       }
9208: #endif
9209:       PetscLayoutReference(mat->cmap, &(*right)->map);
9210:     }
9211:     if (left) {
9213:       VecCreate(PetscObjectComm((PetscObject)mat), left);
9214:       VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE);
9215:       VecSetBlockSize(*left, rbs);
9216:       VecSetType(*left, mat->defaultvectype);
9217: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9218:       if (mat->boundtocpu && mat->bindingpropagates) {
9219:         VecSetBindingPropagates(*left, PETSC_TRUE);
9220:         VecBindToCPU(*left, PETSC_TRUE);
9221:       }
9222: #endif
9223:       PetscLayoutReference(mat->rmap, &(*left)->map);
9224:     }
9225:   }
9226:   return 0;
9227: }

9229: /*@C
9230:    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9231:      with default values.

9233:    Not Collective

9235:    Input Parameters:
9236: .    info - the `MatFactorInfo` data structure

9238:    Level: developer

9240:    Notes:
9241:     The solvers are generally used through the `KSP` and `PC` objects, for example
9242:           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`

9244:     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed

9246:    Developer Note:
9247:    The Fortran interface is not autogenerated as the
9248:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

9250: .seealso: `Mat`, `MatGetFactor()`, `MatFactorInfo`
9251: @*/
9252: PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9253: {
9254:   PetscMemzero(info, sizeof(MatFactorInfo));
9255:   return 0;
9256: }

9258: /*@
9259:    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed

9261:    Collective

9263:    Input Parameters:
9264: +  mat - the factored matrix
9265: -  is - the index set defining the Schur indices (0-based)

9267:    Level: advanced

9269:    Notes:
9270:     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.

9272:    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.

9274:    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`

9276: .seealso: `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9277:           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9278: @*/
9279: PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9280: {
9281:   PetscErrorCode (*f)(Mat, IS);

9289:   PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f);
9291:   MatDestroy(&mat->schur);
9292:   (*f)(mat, is);
9294:   return 0;
9295: }

9297: /*@
9298:   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step

9300:    Logically Collective

9302:    Input Parameters:
9303: +  F - the factored matrix obtained by calling `MatGetFactor()`
9304: .  S - location where to return the Schur complement, can be `NULL`
9305: -  status - the status of the Schur complement matrix, can be `NULL`

9307:    Level: advanced

9309:    Notes:
9310:    You must call `MatFactorSetSchurIS()` before calling this routine.

9312:    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`

9314:    The routine provides a copy of the Schur matrix stored within the solver data structures.
9315:    The caller must destroy the object when it is no longer needed.
9316:    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.

9318:    Use `MatFactorGetSchurComplement()` to get access to the Schur complement matrix inside the factored matrix instead of making a copy of it (which this function does)

9320:    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.

9322:    Developer Note:
9323:     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9324:    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.

9326: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9327: @*/
9328: PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9329: {
9333:   if (S) {
9334:     PetscErrorCode (*f)(Mat, Mat *);

9336:     PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f);
9337:     if (f) {
9338:       (*f)(F, S);
9339:     } else {
9340:       MatDuplicate(F->schur, MAT_COPY_VALUES, S);
9341:     }
9342:   }
9343:   if (status) *status = F->schur_status;
9344:   return 0;
9345: }

9347: /*@
9348:   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix

9350:    Logically Collective

9352:    Input Parameters:
9353: +  F - the factored matrix obtained by calling `MatGetFactor()`
9354: .  *S - location where to return the Schur complement, can be `NULL`
9355: -  status - the status of the Schur complement matrix, can be `NULL`

9357:    Level: advanced

9359:    Notes:
9360:    You must call `MatFactorSetSchurIS()` before calling this routine.

9362:    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`

9364:    The routine returns a the Schur Complement stored within the data structures of the solver.

9366:    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.

9368:    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.

9370:    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix

9372:    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.

9374: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9375: @*/
9376: PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9377: {
9381:   if (S) *S = F->schur;
9382:   if (status) *status = F->schur_status;
9383:   return 0;
9384: }

9386: /*@
9387:   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`

9389:    Logically Collective

9391:    Input Parameters:
9392: +  F - the factored matrix obtained by calling `MatGetFactor()`
9393: .  *S - location where the Schur complement is stored
9394: -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)

9396:    Level: advanced

9398: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9399: @*/
9400: PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9401: {
9403:   if (S) {
9405:     *S = NULL;
9406:   }
9407:   F->schur_status = status;
9408:   MatFactorUpdateSchurStatus_Private(F);
9409:   return 0;
9410: }

9412: /*@
9413:   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step

9415:    Logically Collective

9417:    Input Parameters:
9418: +  F - the factored matrix obtained by calling `MatGetFactor()`
9419: .  rhs - location where the right hand side of the Schur complement system is stored
9420: -  sol - location where the solution of the Schur complement system has to be returned

9422:    Level: advanced

9424:    Notes:
9425:    The sizes of the vectors should match the size of the Schur complement

9427:    Must be called after `MatFactorSetSchurIS()`

9429: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9430: @*/
9431: PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9432: {
9441:   MatFactorFactorizeSchurComplement(F);
9442:   switch (F->schur_status) {
9443:   case MAT_FACTOR_SCHUR_FACTORED:
9444:     MatSolveTranspose(F->schur, rhs, sol);
9445:     break;
9446:   case MAT_FACTOR_SCHUR_INVERTED:
9447:     MatMultTranspose(F->schur, rhs, sol);
9448:     break;
9449:   default:
9450:     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9451:   }
9452:   return 0;
9453: }

9455: /*@
9456:   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step

9458:    Logically Collective

9460:    Input Parameters:
9461: +  F - the factored matrix obtained by calling `MatGetFactor()`
9462: .  rhs - location where the right hand side of the Schur complement system is stored
9463: -  sol - location where the solution of the Schur complement system has to be returned

9465:    Level: advanced

9467:    Notes:
9468:    The sizes of the vectors should match the size of the Schur complement

9470:    Must be called after `MatFactorSetSchurIS()`

9472: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9473: @*/
9474: PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9475: {
9484:   MatFactorFactorizeSchurComplement(F);
9485:   switch (F->schur_status) {
9486:   case MAT_FACTOR_SCHUR_FACTORED:
9487:     MatSolve(F->schur, rhs, sol);
9488:     break;
9489:   case MAT_FACTOR_SCHUR_INVERTED:
9490:     MatMult(F->schur, rhs, sol);
9491:     break;
9492:   default:
9493:     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9494:   }
9495:   return 0;
9496: }

9498: /*@
9499:   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step

9501:    Logically Collective on F

9503:    Input Parameters:
9504: .  F - the factored matrix obtained by calling `MatGetFactor()`

9506:    Level: advanced

9508:    Notes:
9509:     Must be called after `MatFactorSetSchurIS()`.

9511:    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.

9513: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9514: @*/
9515: PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9516: {
9519:   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) return 0;
9520:   MatFactorFactorizeSchurComplement(F);
9521:   MatFactorInvertSchurComplement_Private(F);
9522:   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9523:   return 0;
9524: }

9526: /*@
9527:   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step

9529:    Logically Collective

9531:    Input Parameters:
9532: .  F - the factored matrix obtained by calling `MatGetFactor()`

9534:    Level: advanced

9536:    Note:
9537:     Must be called after `MatFactorSetSchurIS()`

9539: .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9540: @*/
9541: PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9542: {
9545:   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) return 0;
9546:   MatFactorFactorizeSchurComplement_Private(F);
9547:   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9548:   return 0;
9549: }

9551: /*@
9552:    MatPtAP - Creates the matrix product C = P^T * A * P

9554:    Neighbor-wise Collective

9556:    Input Parameters:
9557: +  A - the matrix
9558: .  P - the projection matrix
9559: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9560: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9561:           if the result is a dense matrix this is irrelevant

9563:    Output Parameters:
9564: .  C - the product matrix

9566:    Level: intermediate

9568:    Notes:
9569:    C will be created and must be destroyed by the user with `MatDestroy()`.

9571:    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done

9573:    Developer Note:
9574:    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.

9576: .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9577: @*/
9578: PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9579: {
9580:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);

9583:   if (scall == MAT_INITIAL_MATRIX) {
9584:     MatProductCreate(A, P, NULL, C);
9585:     MatProductSetType(*C, MATPRODUCT_PtAP);
9586:     MatProductSetAlgorithm(*C, "default");
9587:     MatProductSetFill(*C, fill);

9589:     (*C)->product->api_user = PETSC_TRUE;
9590:     MatProductSetFromOptions(*C);
9592:     MatProductSymbolic(*C);
9593:   } else { /* scall == MAT_REUSE_MATRIX */
9594:     MatProductReplaceMats(A, P, NULL, *C);
9595:   }

9597:   MatProductNumeric(*C);
9598:   (*C)->symmetric = A->symmetric;
9599:   (*C)->spd       = A->spd;
9600:   return 0;
9601: }

9603: /*@
9604:    MatRARt - Creates the matrix product C = R * A * R^T

9606:    Neighbor-wise Collective

9608:    Input Parameters:
9609: +  A - the matrix
9610: .  R - the projection matrix
9611: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9612: -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9613:           if the result is a dense matrix this is irrelevant

9615:    Output Parameters:
9616: .  C - the product matrix

9618:    Level: intermediate

9620:    Notes:
9621:    C will be created and must be destroyed by the user with `MatDestroy()`.

9623:    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done

9625:    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9626:    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9627:    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9628:    We recommend using MatPtAP().

9630: .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9631: @*/
9632: PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9633: {
9634:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);

9637:   if (scall == MAT_INITIAL_MATRIX) {
9638:     MatProductCreate(A, R, NULL, C);
9639:     MatProductSetType(*C, MATPRODUCT_RARt);
9640:     MatProductSetAlgorithm(*C, "default");
9641:     MatProductSetFill(*C, fill);

9643:     (*C)->product->api_user = PETSC_TRUE;
9644:     MatProductSetFromOptions(*C);
9646:     MatProductSymbolic(*C);
9647:   } else { /* scall == MAT_REUSE_MATRIX */
9648:     MatProductReplaceMats(A, R, NULL, *C);
9649:   }

9651:   MatProductNumeric(*C);
9652:   if (A->symmetric == PETSC_BOOL3_TRUE) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9653:   return 0;
9654: }

9656: static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9657: {

9660:   if (scall == MAT_INITIAL_MATRIX) {
9661:     PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]);
9662:     MatProductCreate(A, B, NULL, C);
9663:     MatProductSetType(*C, ptype);
9664:     MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT);
9665:     MatProductSetFill(*C, fill);

9667:     (*C)->product->api_user = PETSC_TRUE;
9668:     MatProductSetFromOptions(*C);
9669:     MatProductSymbolic(*C);
9670:   } else { /* scall == MAT_REUSE_MATRIX */
9671:     Mat_Product *product = (*C)->product;
9672:     PetscBool    isdense;

9674:     PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "");
9675:     if (isdense && product && product->type != ptype) {
9676:       MatProductClear(*C);
9677:       product = NULL;
9678:     }
9679:     PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]);
9680:     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9681:       if (isdense) {
9682:         MatProductCreate_Private(A, B, NULL, *C);
9683:         product           = (*C)->product;
9684:         product->fill     = fill;
9685:         product->api_user = PETSC_TRUE;
9686:         product->clear    = PETSC_TRUE;

9688:         MatProductSetType(*C, ptype);
9689:         MatProductSetFromOptions(*C);
9691:         MatProductSymbolic(*C);
9692:       } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9693:     } else { /* user may change input matrices A or B when REUSE */
9694:       MatProductReplaceMats(A, B, NULL, *C);
9695:     }
9696:   }
9697:   MatProductNumeric(*C);
9698:   return 0;
9699: }

9701: /*@
9702:    MatMatMult - Performs matrix-matrix multiplication C=A*B.

9704:    Neighbor-wise Collective

9706:    Input Parameters:
9707: +  A - the left matrix
9708: .  B - the right matrix
9709: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9710: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9711:           if the result is a dense matrix this is irrelevant

9713:    Output Parameters:
9714: .  C - the product matrix

9716:    Notes:
9717:    Unless scall is `MAT_REUSE_MATRIX` C will be created.

9719:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call and C was obtained from a previous
9720:    call to this function with `MAT_INITIAL_MATRIX`.

9722:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.

9724:    In the special case where matrix B (and hence C) are dense you can create the correctly sized matrix C yourself and then call this routine with `MAT_REUSE_MATRIX`,
9725:    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.

9727:    Example of Usage:
9728: .vb
9729:      MatProductCreate(A,B,NULL,&C);
9730:      MatProductSetType(C,MATPRODUCT_AB);
9731:      MatProductSymbolic(C);
9732:      MatProductNumeric(C); // compute C=A * B
9733:      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9734:      MatProductNumeric(C);
9735:      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9736:      MatProductNumeric(C);
9737: .ve

9739:    Level: intermediate

9741: .seealso: `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9742: @*/
9743: PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9744: {
9745:   MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C);
9746:   return 0;
9747: }

9749: /*@
9750:    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.

9752:    Neighbor-wise Collective

9754:    Input Parameters:
9755: +  A - the left matrix
9756: .  B - the right matrix
9757: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9758: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known

9760:    Output Parameters:
9761: .  C - the product matrix

9763:    Level: intermediate

9765:    Notes:
9766:    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.

9768:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call

9770:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9771:    actually needed.

9773:    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9774:    and for pairs of `MATMPIDENSE` matrices.

9776:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`

9778:    Options Database Keys:
9779: .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9780:               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9781:               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.

9783: .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9784: @*/
9785: PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9786: {
9787:   MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C);
9788:   if (A == B) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9789:   return 0;
9790: }

9792: /*@
9793:    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.

9795:    Neighbor-wise Collective

9797:    Input Parameters:
9798: +  A - the left matrix
9799: .  B - the right matrix
9800: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9801: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known

9803:    Output Parameters:
9804: .  C - the product matrix

9806:    Level: intermediate

9808:    Notes:
9809:    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.

9811:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.

9813:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`

9815:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9816:    actually needed.

9818:    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9819:    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.

9821: .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9822: @*/
9823: PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9824: {
9825:   MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C);
9826:   return 0;
9827: }

9829: /*@
9830:    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.

9832:    Neighbor-wise Collective

9834:    Input Parameters:
9835: +  A - the left matrix
9836: .  B - the middle matrix
9837: .  C - the right matrix
9838: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9839: -  fill - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DEFAULT` if you do not have a good estimate
9840:           if the result is a dense matrix this is irrelevant

9842:    Output Parameters:
9843: .  D - the product matrix

9845:    Level: intermediate

9847:    Notes:
9848:    Unless scall is `MAT_REUSE_MATRIX` D will be created.

9850:    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call

9852:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`

9854:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9855:    actually needed.

9857:    If you have many matrices with the same non-zero structure to multiply, you
9858:    should use `MAT_REUSE_MATRIX` in all calls but the first

9860: .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9861: @*/
9862: PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
9863: {
9864:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);

9867:   if (scall == MAT_INITIAL_MATRIX) {
9868:     MatProductCreate(A, B, C, D);
9869:     MatProductSetType(*D, MATPRODUCT_ABC);
9870:     MatProductSetAlgorithm(*D, "default");
9871:     MatProductSetFill(*D, fill);

9873:     (*D)->product->api_user = PETSC_TRUE;
9874:     MatProductSetFromOptions(*D);
9876:                ((PetscObject)C)->type_name);
9877:     MatProductSymbolic(*D);
9878:   } else { /* user may change input matrices when REUSE */
9879:     MatProductReplaceMats(A, B, C, *D);
9880:   }
9881:   MatProductNumeric(*D);
9882:   return 0;
9883: }

9885: /*@
9886:    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.

9888:    Collective

9890:    Input Parameters:
9891: +  mat - the matrix
9892: .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9893: .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
9894: -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

9896:    Output Parameter:
9897: .  matredundant - redundant matrix

9899:    Level: advanced

9901:    Notes:
9902:    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
9903:    original matrix has not changed from that last call to MatCreateRedundantMatrix().

9905:    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9906:    calling it.

9908:    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.

9910: .seealso: `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
9911: @*/
9912: PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
9913: {
9914:   MPI_Comm       comm;
9915:   PetscMPIInt    size;
9916:   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9917:   Mat_Redundant *redund     = NULL;
9918:   PetscSubcomm   psubcomm   = NULL;
9919:   MPI_Comm       subcomm_in = subcomm;
9920:   Mat           *matseq;
9921:   IS             isrow, iscol;
9922:   PetscBool      newsubcomm = PETSC_FALSE;

9925:   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9928:   }

9930:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
9931:   if (size == 1 || nsubcomm == 1) {
9932:     if (reuse == MAT_INITIAL_MATRIX) {
9933:       MatDuplicate(mat, MAT_COPY_VALUES, matredundant);
9934:     } else {
9936:       MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN);
9937:     }
9938:     return 0;
9939:   }

9943:   MatCheckPreallocated(mat, 1);

9945:   PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0);
9946:   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9947:     /* create psubcomm, then get subcomm */
9948:     PetscObjectGetComm((PetscObject)mat, &comm);
9949:     MPI_Comm_size(comm, &size);

9952:     PetscSubcommCreate(comm, &psubcomm);
9953:     PetscSubcommSetNumber(psubcomm, nsubcomm);
9954:     PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS);
9955:     PetscSubcommSetFromOptions(psubcomm);
9956:     PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL);
9957:     newsubcomm = PETSC_TRUE;
9958:     PetscSubcommDestroy(&psubcomm);
9959:   }

9961:   /* get isrow, iscol and a local sequential matrix matseq[0] */
9962:   if (reuse == MAT_INITIAL_MATRIX) {
9963:     mloc_sub = PETSC_DECIDE;
9964:     nloc_sub = PETSC_DECIDE;
9965:     if (bs < 1) {
9966:       PetscSplitOwnership(subcomm, &mloc_sub, &M);
9967:       PetscSplitOwnership(subcomm, &nloc_sub, &N);
9968:     } else {
9969:       PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M);
9970:       PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N);
9971:     }
9972:     MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm);
9973:     rstart = rend - mloc_sub;
9974:     ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow);
9975:     ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol);
9976:   } else { /* reuse == MAT_REUSE_MATRIX */
9978:     /* retrieve subcomm */
9979:     PetscObjectGetComm((PetscObject)(*matredundant), &subcomm);
9980:     redund = (*matredundant)->redundant;
9981:     isrow  = redund->isrow;
9982:     iscol  = redund->iscol;
9983:     matseq = redund->matseq;
9984:   }
9985:   MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq);

9987:   /* get matredundant over subcomm */
9988:   if (reuse == MAT_INITIAL_MATRIX) {
9989:     MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant);

9991:     /* create a supporting struct and attach it to C for reuse */
9992:     PetscNew(&redund);
9993:     (*matredundant)->redundant = redund;
9994:     redund->isrow              = isrow;
9995:     redund->iscol              = iscol;
9996:     redund->matseq             = matseq;
9997:     if (newsubcomm) {
9998:       redund->subcomm = subcomm;
9999:     } else {
10000:       redund->subcomm = MPI_COMM_NULL;
10001:     }
10002:   } else {
10003:     MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant);
10004:   }
10005: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10006:   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10007:     MatBindToCPU(*matredundant, PETSC_TRUE);
10008:     MatSetBindingPropagates(*matredundant, PETSC_TRUE);
10009:   }
10010: #endif
10011:   PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0);
10012:   return 0;
10013: }

10015: /*@C
10016:    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10017:    a given `Mat`. Each submatrix can span multiple procs.

10019:    Collective

10021:    Input Parameters:
10022: +  mat - the matrix
10023: .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10024: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

10026:    Output Parameter:
10027: .  subMat - parallel sub-matrices each spanning a given `subcomm`

10029:   Level: advanced

10031:   Notes:
10032:   The submatrix partition across processors is dictated by `subComm` a
10033:   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10034:   is not restricted to be grouped with consecutive original ranks.

10036:   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10037:   map directly to the layout of the original matrix [wrt the local
10038:   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10039:   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10040:   the `subMat`. However the offDiagMat looses some columns - and this is
10041:   reconstructed with `MatSetValues()`

10043:   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks

10045: .seealso: `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10046: @*/
10047: PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10048: {
10049:   PetscMPIInt commsize, subCommSize;

10051:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize);
10052:   MPI_Comm_size(subComm, &subCommSize);

10056:   PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10057:   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10058:   PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10059:   return 0;
10060: }

10062: /*@
10063:    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering

10065:    Not Collective

10067:    Input Parameters:
10068: +  mat - matrix to extract local submatrix from
10069: .  isrow - local row indices for submatrix
10070: -  iscol - local column indices for submatrix

10072:    Output Parameter:
10073: .  submat - the submatrix

10075:    Level: intermediate

10077:    Notes:
10078:    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.

10080:    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10081:    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.

10083:    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10084:    `MatSetValuesBlockedLocal()` will also be implemented.

10086:    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10087:    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.

10089: .seealso: `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10090: @*/
10091: PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10092: {

10100:   if (mat->ops->getlocalsubmatrix) {
10101:     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10102:   } else {
10103:     MatCreateLocalRef(mat, isrow, iscol, submat);
10104:   }
10105:   return 0;
10106: }

10108: /*@
10109:    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`

10111:    Not Collective

10113:    Input Parameters:
10114: +  mat - matrix to extract local submatrix from
10115: .  isrow - local row indices for submatrix
10116: .  iscol - local column indices for submatrix
10117: -  submat - the submatrix

10119:    Level: intermediate

10121: .seealso: `Mat`, `MatGetLocalSubMatrix()`
10122: @*/
10123: PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10124: {

10132:   if (mat->ops->restorelocalsubmatrix) {
10133:     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10134:   } else {
10135:     MatDestroy(submat);
10136:   }
10137:   *submat = NULL;
10138:   return 0;
10139: }

10141: /*@
10142:    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix

10144:    Collective

10146:    Input Parameter:
10147: .  mat - the matrix

10149:    Output Parameter:
10150: .  is - if any rows have zero diagonals this contains the list of them

10152:    Level: developer

10154: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10155: @*/
10156: PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10157: {

10163:   if (!mat->ops->findzerodiagonals) {
10164:     Vec                diag;
10165:     const PetscScalar *a;
10166:     PetscInt          *rows;
10167:     PetscInt           rStart, rEnd, r, nrow = 0;

10169:     MatCreateVecs(mat, &diag, NULL);
10170:     MatGetDiagonal(mat, diag);
10171:     MatGetOwnershipRange(mat, &rStart, &rEnd);
10172:     VecGetArrayRead(diag, &a);
10173:     for (r = 0; r < rEnd - rStart; ++r)
10174:       if (a[r] == 0.0) ++nrow;
10175:     PetscMalloc1(nrow, &rows);
10176:     nrow = 0;
10177:     for (r = 0; r < rEnd - rStart; ++r)
10178:       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10179:     VecRestoreArrayRead(diag, &a);
10180:     VecDestroy(&diag);
10181:     ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is);
10182:   } else {
10183:     PetscUseTypeMethod(mat, findzerodiagonals, is);
10184:   }
10185:   return 0;
10186: }

10188: /*@
10189:    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)

10191:    Collective

10193:    Input Parameter:
10194: .  mat - the matrix

10196:    Output Parameter:
10197: .  is - contains the list of rows with off block diagonal entries

10199:    Level: developer

10201: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10202: @*/
10203: PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10204: {

10210:   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10211:   return 0;
10212: }

10214: /*@C
10215:   MatInvertBlockDiagonal - Inverts the block diagonal entries.

10217:   Collective; No Fortran Support

10219:   Input Parameters:
10220: . mat - the matrix

10222:   Output Parameters:
10223: . values - the block inverses in column major order (FORTRAN-like)

10225:   Level: advanced

10227:    Notes:
10228:    The size of the blocks is determined by the block size of the matrix.

10230:    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case

10232:    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size

10234: .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10235: @*/
10236: PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10237: {
10241:   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10242:   return 0;
10243: }

10245: /*@C
10246:   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.

10248:   Collective; No Fortran Support

10250:   Input Parameters:
10251: + mat - the matrix
10252: . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10253: - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`

10255:   Output Parameters:
10256: . values - the block inverses in column major order (FORTRAN-like)

10258:   Level: advanced

10260:   Notes:
10261:   Use `MatInvertBlockDiagonal()` if all blocks have the same size

10263:   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case

10265: .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10266: @*/
10267: PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10268: {
10272:   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10273:   return 0;
10274: }

10276: /*@
10277:   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A

10279:   Collective on Mat

10281:   Input Parameters:
10282: + A - the matrix
10283: - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.

10285:   Level: advanced

10287:   Note:
10288:   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`

10290: .seealso: `Mat`, `MatInvertBlockDiagonal()`
10291: @*/
10292: PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10293: {
10294:   const PetscScalar *vals;
10295:   PetscInt          *dnnz;
10296:   PetscInt           m, rstart, rend, bs, i, j;

10298:   MatInvertBlockDiagonal(A, &vals);
10299:   MatGetBlockSize(A, &bs);
10300:   MatGetLocalSize(A, &m, NULL);
10301:   MatSetLayouts(C, A->rmap, A->cmap);
10302:   PetscMalloc1(m / bs, &dnnz);
10303:   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10304:   MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL);
10305:   PetscFree(dnnz);
10306:   MatGetOwnershipRange(C, &rstart, &rend);
10307:   MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE);
10308:   for (i = rstart / bs; i < rend / bs; i++) MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES);
10309:   MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY);
10310:   MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY);
10311:   MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE);
10312:   return 0;
10313: }

10315: /*@C
10316:     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10317:     via `MatTransposeColoringCreate()`.

10319:     Collective on c

10321:     Input Parameter:
10322: .   c - coloring context

10324:     Level: intermediate

10326: .seealso: `Mat`, `MatTransposeColoringCreate()`
10327: @*/
10328: PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10329: {
10330:   MatTransposeColoring matcolor = *c;

10332:   if (!matcolor) return 0;
10333:   if (--((PetscObject)matcolor)->refct > 0) {
10334:     matcolor = NULL;
10335:     return 0;
10336:   }

10338:   PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow);
10339:   PetscFree(matcolor->rows);
10340:   PetscFree(matcolor->den2sp);
10341:   PetscFree(matcolor->colorforcol);
10342:   PetscFree(matcolor->columns);
10343:   if (matcolor->brows > 0) PetscFree(matcolor->lstart);
10344:   PetscHeaderDestroy(c);
10345:   return 0;
10346: }

10348: /*@C
10349:     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10350:     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10351:     `MatTransposeColoring` to sparse B.

10353:     Collective on coloring

10355:     Input Parameters:
10356: +   B - sparse matrix B
10357: .   Btdense - symbolic dense matrix B^T
10358: -   coloring - coloring context created with `MatTransposeColoringCreate()`

10360:     Output Parameter:
10361: .   Btdense - dense matrix B^T

10363:     Level: developer

10365:     Note:
10366:     These are used internally for some implementations of `MatRARt()`

10368: .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10369: @*/
10370: PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10371: {

10376:   (B->ops->transcoloringapplysptoden)(coloring, B, Btdense);
10377:   return 0;
10378: }

10380: /*@C
10381:     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10382:     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10383:     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10384:     Csp from Cden.

10386:     Collective

10388:     Input Parameters:
10389: +   coloring - coloring context created with `MatTransposeColoringCreate()`
10390: -   Cden - matrix product of a sparse matrix and a dense matrix Btdense

10392:     Output Parameter:
10393: .   Csp - sparse matrix

10395:     Level: developer

10397:     Note:
10398:     These are used internally for some implementations of `MatRARt()`

10400: .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10401: @*/
10402: PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10403: {

10408:   (Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp);
10409:   MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY);
10410:   MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY);
10411:   return 0;
10412: }

10414: /*@C
10415:    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.

10417:    Collective

10419:    Input Parameters:
10420: +  mat - the matrix product C
10421: -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`

10423:     Output Parameter:
10424: .   color - the new coloring context

10426:     Level: intermediate

10428: .seealso: `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10429:           `MatTransColoringApplyDenToSp()`
10430: @*/
10431: PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10432: {
10433:   MatTransposeColoring c;
10434:   MPI_Comm             comm;

10436:   PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10437:   PetscObjectGetComm((PetscObject)mat, &comm);
10438:   PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL);

10440:   c->ctype = iscoloring->ctype;
10441:   if (mat->ops->transposecoloringcreate) {
10442:     PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10443:   } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);

10445:   *color = c;
10446:   PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10447:   return 0;
10448: }

10450: /*@
10451:       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10452:         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10453:         same, otherwise it will be larger

10455:      Not Collective

10457:   Input Parameter:
10458: .    A  - the matrix

10460:   Output Parameter:
10461: .    state - the current state

10463:   Level: intermediate

10465:   Notes:
10466:     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10467:          different matrices

10469:     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix

10471:     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.

10473: .seealso: `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10474: @*/
10475: PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10476: {
10478:   *state = mat->nonzerostate;
10479:   return 0;
10480: }

10482: /*@
10483:       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10484:                  matrices from each processor

10486:     Collective

10488:    Input Parameters:
10489: +    comm - the communicators the parallel matrix will live on
10490: .    seqmat - the input sequential matrices
10491: .    n - number of local columns (or `PETSC_DECIDE`)
10492: -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

10494:    Output Parameter:
10495: .    mpimat - the parallel matrix generated

10497:     Level: developer

10499:    Note:
10500:     The number of columns of the matrix in EACH processor MUST be the same.

10502: .seealso: `Mat`
10503: @*/
10504: PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10505: {
10506:   PetscMPIInt size;

10508:   MPI_Comm_size(comm, &size);
10509:   if (size == 1) {
10510:     if (reuse == MAT_INITIAL_MATRIX) {
10511:       MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat);
10512:     } else {
10513:       MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN);
10514:     }
10515:     return 0;
10516:   }


10520:   PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0);
10521:   (*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat);
10522:   PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0);
10523:   return 0;
10524: }

10526: /*@
10527:      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.

10529:     Collective

10531:    Input Parameters:
10532: +    A   - the matrix to create subdomains from
10533: -    N   - requested number of subdomains

10535:    Output Parameters:
10536: +    n   - number of subdomains resulting on this rank
10537: -    iss - `IS` list with indices of subdomains on this rank

10539:     Level: advanced

10541:     Note:
10542:     The number of subdomains must be smaller than the communicator size

10544: .seealso: `Mat`, `IS`
10545: @*/
10546: PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10547: {
10548:   MPI_Comm    comm, subcomm;
10549:   PetscMPIInt size, rank, color;
10550:   PetscInt    rstart, rend, k;

10552:   PetscObjectGetComm((PetscObject)A, &comm);
10553:   MPI_Comm_size(comm, &size);
10554:   MPI_Comm_rank(comm, &rank);
10556:   *n    = 1;
10557:   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10558:   color = rank / k;
10559:   MPI_Comm_split(comm, color, rank, &subcomm);
10560:   PetscMalloc1(1, iss);
10561:   MatGetOwnershipRange(A, &rstart, &rend);
10562:   ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]);
10563:   MPI_Comm_free(&subcomm);
10564:   return 0;
10565: }

10567: /*@
10568:    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.

10570:    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10571:    If they are not the same, uses `MatMatMatMult()`.

10573:    Once the coarse grid problem is constructed, correct for interpolation operators
10574:    that are not of full rank, which can legitimately happen in the case of non-nested
10575:    geometric multigrid.

10577:    Input Parameters:
10578: +  restrct - restriction operator
10579: .  dA - fine grid matrix
10580: .  interpolate - interpolation operator
10581: .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10582: -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate

10584:    Output Parameters:
10585: .  A - the Galerkin coarse matrix

10587:    Options Database Key:
10588: .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used

10590:    Level: developer

10592: .seealso: `Mat`, `MatPtAP()`, `MatMatMatMult()`
10593: @*/
10594: PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10595: {
10596:   IS  zerorows;
10597:   Vec diag;

10600:   /* Construct the coarse grid matrix */
10601:   if (interpolate == restrct) {
10602:     MatPtAP(dA, interpolate, reuse, fill, A);
10603:   } else {
10604:     MatMatMatMult(restrct, dA, interpolate, reuse, fill, A);
10605:   }

10607:   /* If the interpolation matrix is not of full rank, A will have zero rows.
10608:      This can legitimately happen in the case of non-nested geometric multigrid.
10609:      In that event, we set the rows of the matrix to the rows of the identity,
10610:      ignoring the equations (as the RHS will also be zero). */

10612:   MatFindZeroRows(*A, &zerorows);

10614:   if (zerorows != NULL) { /* if there are any zero rows */
10615:     MatCreateVecs(*A, &diag, NULL);
10616:     MatGetDiagonal(*A, diag);
10617:     VecISSet(diag, zerorows, 1.0);
10618:     MatDiagonalSet(*A, diag, INSERT_VALUES);
10619:     VecDestroy(&diag);
10620:     ISDestroy(&zerorows);
10621:   }
10622:   return 0;
10623: }

10625: /*@C
10626:     MatSetOperation - Allows user to set a matrix operation for any matrix type

10628:    Logically Collective

10630:     Input Parameters:
10631: +   mat - the matrix
10632: .   op - the name of the operation
10633: -   f - the function that provides the operation

10635:    Level: developer

10637:     Usage:
10638: .vb
10639:   extern PetscErrorCode usermult(Mat, Vec, Vec);

10641:   MatCreateXXX(comm, ..., &A);
10642:   MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult);
10643: .ve

10645:     Notes:
10646:     See the file `include/petscmat.h` for a complete list of matrix
10647:     operations, which all have the form MATOP_<OPERATION>, where
10648:     <OPERATION> is the name (in all capital letters) of the
10649:     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).

10651:     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10652:     sequence as the usual matrix interface routines, since they
10653:     are intended to be accessed via the usual matrix interface
10654:     routines, e.g.,
10655: .vb
10656:   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10657: .ve

10659:     In particular each function MUST return `PETSC_SUCCESS` on success and
10660:     nonzero on failure.

10662:     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.

10664: .seealso: `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10665: @*/
10666: PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10667: {
10669:   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10670:   (((void (**)(void))mat->ops)[op]) = f;
10671:   return 0;
10672: }

10674: /*@C
10675:     MatGetOperation - Gets a matrix operation for any matrix type.

10677:     Not Collective

10679:     Input Parameters:
10680: +   mat - the matrix
10681: -   op - the name of the operation

10683:     Output Parameter:
10684: .   f - the function that provides the operation

10686:     Level: developer

10688:     Usage:
10689: $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10690: $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);

10692:     Notes:
10693:     See the file include/petscmat.h for a complete list of matrix
10694:     operations, which all have the form MATOP_<OPERATION>, where
10695:     <OPERATION> is the name (in all capital letters) of the
10696:     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).

10698:     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.

10700: .seealso: `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10701: @*/
10702: PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10703: {
10705:   *f = (((void (**)(void))mat->ops)[op]);
10706:   return 0;
10707: }

10709: /*@
10710:     MatHasOperation - Determines whether the given matrix supports the particular operation.

10712:    Not Collective

10714:    Input Parameters:
10715: +  mat - the matrix
10716: -  op - the operation, for example, `MATOP_GET_DIAGONAL`

10718:    Output Parameter:
10719: .  has - either `PETSC_TRUE` or `PETSC_FALSE`

10721:    Level: advanced

10723:    Note:
10724:    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.

10726: .seealso: `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10727: @*/
10728: PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10729: {
10732:   if (mat->ops->hasoperation) {
10733:     PetscUseTypeMethod(mat, hasoperation, op, has);
10734:   } else {
10735:     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10736:     else {
10737:       *has = PETSC_FALSE;
10738:       if (op == MATOP_CREATE_SUBMATRIX) {
10739:         PetscMPIInt size;

10741:         MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
10742:         if (size == 1) MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has);
10743:       }
10744:     }
10745:   }
10746:   return 0;
10747: }

10749: /*@
10750:     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent

10752:    Collective

10754:    Input Parameters:
10755: .  mat - the matrix

10757:    Output Parameter:
10758: .  cong - either `PETSC_TRUE` or `PETSC_FALSE`

10760:    Level: beginner

10762: .seealso: `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10763: @*/
10764: PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10765: {
10769:   if (!mat->rmap || !mat->cmap) {
10770:     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10771:     return 0;
10772:   }
10773:   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10774:     PetscLayoutSetUp(mat->rmap);
10775:     PetscLayoutSetUp(mat->cmap);
10776:     PetscLayoutCompare(mat->rmap, mat->cmap, cong);
10777:     if (*cong) mat->congruentlayouts = 1;
10778:     else mat->congruentlayouts = 0;
10779:   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10780:   return 0;
10781: }

10783: PetscErrorCode MatSetInf(Mat A)
10784: {
10785:   PetscUseTypeMethod(A, setinf);
10786:   return 0;
10787: }

10789: /*C
10790:    MatCreateGraph - create a scalar matrix (that is a matrix with one vertex for each block vertex in the original matrix), for use in graph algorithms
10791:    and possibly removes small values from the graph structure.

10793:    Collective

10795:    Input Parameters:
10796: +  A - the matrix
10797: .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
10798: .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
10799: -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value

10801:    Output Parameter:
10802: .  graph - the resulting graph

10804:    Level: advanced

10806: .seealso: `Mat`, `MatCreate()`, `PCGAMG`
10807: */
10808: PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
10809: {
10813:   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
10814:   return 0;
10815: }