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:
 64: .vb
 65:      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
 66:      MatSetRandom(x,rctx);
 67:      PetscRandomDestroy(rctx);
 68: .ve

 70:    Level: intermediate

 72:    Notes:
 73:    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,

 75:    for sparse matrices that already have locations it fills the locations with random numbers.

 77:    It generates an error if used on sparse matrices that have not been preallocated.

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

 85:   PetscFunctionBegin;
 89:   MatCheckPreallocated(x, 1);

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

103:   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
104:   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
105:   PetscCall(PetscRandomDestroy(&randObj));
106:   PetscFunctionReturn(PETSC_SUCCESS);
107: }

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

112:    Logically Collective

114:    Input Parameter:
115: .  mat - the factored matrix

117:    Output Parameters:
118: +  pivot - the pivot value computed
119: -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
120:          the share the matrix

122:    Level: advanced

124:    Notes:
125:     This routine does not work for factorizations done with external packages.

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

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

131: .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
132:           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
133: @*/
134: PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
135: {
136:   PetscFunctionBegin;
140:   *pivot = mat->factorerror_zeropivot_value;
141:   *row   = mat->factorerror_zeropivot_row;
142:   PetscFunctionReturn(PETSC_SUCCESS);
143: }

145: /*@
146:    MatFactorGetError - gets the error code from a factorization

148:    Logically Collective

150:    Input Parameters:
151: .  mat - the factored matrix

153:    Output Parameter:
154: .  err  - the error code

156:    Level: advanced

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

161: .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
162:           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
163: @*/
164: PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
165: {
166:   PetscFunctionBegin;
169:   *err = mat->factorerrortype;
170:   PetscFunctionReturn(PETSC_SUCCESS);
171: }

173: /*@
174:    MatFactorClearError - clears the error code in a factorization

176:    Logically Collective

178:    Input Parameter:
179: .  mat - the factored matrix

181:    Level: developer

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

186: .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
187:           `MatGetErrorCode()`, `MatFactorError`
188: @*/
189: PetscErrorCode MatFactorClearError(Mat mat)
190: {
191:   PetscFunctionBegin;
193:   mat->factorerrortype             = MAT_FACTOR_NOERROR;
194:   mat->factorerror_zeropivot_value = 0.0;
195:   mat->factorerror_zeropivot_row   = 0;
196:   PetscFunctionReturn(PETSC_SUCCESS);
197: }

199: PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
200: {
201:   Vec                r, l;
202:   const PetscScalar *al;
203:   PetscInt           i, nz, gnz, N, n;

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

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

257:   Input Parameter:
258: .    A  - the matrix

260:   Output Parameter:
261: .    keptrows - the rows that are not completely zero

263:   Level: intermediate

265:   Note:
266:     `keptrows` is set to `NULL` if all rows are nonzero.

268: .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()`
269:  @*/
270: PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
271: {
272:   PetscFunctionBegin;
276:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
277:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
278:   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
279:   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
280:   PetscFunctionReturn(PETSC_SUCCESS);
281: }

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

286:   Input Parameter:
287: .    A  - the matrix

289:   Output Parameter:
290: .    zerorows - the rows that are completely zero

292:   Level: intermediate

294:   Note:
295:     `zerorows` is set to `NULL` if no rows are zero.

297: .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()`
298:  @*/
299: PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
300: {
301:   IS       keptrows;
302:   PetscInt m, n;

304:   PetscFunctionBegin;
308:   PetscCall(MatFindNonzeroRows(mat, &keptrows));
309:   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
310:      In keeping with this convention, we set zerorows to NULL if there are no zero
311:      rows. */
312:   if (keptrows == NULL) {
313:     *zerorows = NULL;
314:   } else {
315:     PetscCall(MatGetOwnershipRange(mat, &m, &n));
316:     PetscCall(ISComplement(keptrows, m, n, zerorows));
317:     PetscCall(ISDestroy(&keptrows));
318:   }
319:   PetscFunctionReturn(PETSC_SUCCESS);
320: }

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

325:    Not Collective

327:    Input Parameters:
328: .   A - the matrix

330:    Output Parameters:
331: .   a - the diagonal part (which is a SEQUENTIAL matrix)

333:    Level: advanced

335:    Notes:
336:    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.

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

340: .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
341: @*/
342: PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
343: {
344:   PetscFunctionBegin;
348:   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
349:   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
350:   else {
351:     PetscMPIInt size;

353:     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
354:     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
355:     *a = A;
356:   }
357:   PetscFunctionReturn(PETSC_SUCCESS);
358: }

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

363:    Collective

365:    Input Parameters:
366: .  mat - the matrix

368:    Output Parameter:
369: .   trace - the sum of the diagonal entries

371:    Level: advanced

373: .seealso: [](chapter_matrices), `Mat`
374: @*/
375: PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
376: {
377:   Vec diag;

379:   PetscFunctionBegin;
382:   PetscCall(MatCreateVecs(mat, &diag, NULL));
383:   PetscCall(MatGetDiagonal(mat, diag));
384:   PetscCall(VecSum(diag, trace));
385:   PetscCall(VecDestroy(&diag));
386:   PetscFunctionReturn(PETSC_SUCCESS);
387: }

389: /*@
390:    MatRealPart - Zeros out the imaginary part of the matrix

392:    Logically Collective

394:    Input Parameters:
395: .  mat - the matrix

397:    Level: advanced

399: .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()`
400: @*/
401: PetscErrorCode MatRealPart(Mat mat)
402: {
403:   PetscFunctionBegin;
406:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
407:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
408:   MatCheckPreallocated(mat, 1);
409:   PetscUseTypeMethod(mat, realpart);
410:   PetscFunctionReturn(PETSC_SUCCESS);
411: }

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

416:    Collective

418:    Input Parameter:
419: .  mat - the matrix

421:    Output Parameters:
422: +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
423: -   ghosts - the global indices of the ghost points

425:    Level: advanced

427:    Note:
428:    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`

430: .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()`
431: @*/
432: PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
433: {
434:   PetscFunctionBegin;
437:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
438:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
439:   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
440:   else {
441:     if (nghosts) *nghosts = 0;
442:     if (ghosts) *ghosts = NULL;
443:   }
444:   PetscFunctionReturn(PETSC_SUCCESS);
445: }

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

450:    Logically Collective

452:    Input Parameters:
453: .  mat - the matrix

455:    Level: advanced

457: .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`
458: @*/
459: PetscErrorCode MatImaginaryPart(Mat mat)
460: {
461:   PetscFunctionBegin;
464:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
465:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
466:   MatCheckPreallocated(mat, 1);
467:   PetscUseTypeMethod(mat, imaginarypart);
468:   PetscFunctionReturn(PETSC_SUCCESS);
469: }

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

474:    Not Collective

476:    Input Parameter:
477: .  mat - the matrix

479:    Output Parameters:
480: +  missing - is any diagonal missing
481: -  dd - first diagonal entry that is missing (optional) on this process

483:    Level: advanced

485: .seealso: [](chapter_matrices), `Mat`
486: @*/
487: PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
488: {
489:   PetscFunctionBegin;
493:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
494:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
495:   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
496:   PetscFunctionReturn(PETSC_SUCCESS);
497: }

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

504:    Not Collective

506:    Input Parameters:
507: +  mat - the matrix
508: -  row - the row to get

510:    Output Parameters:
511: +  ncols -  if not `NULL`, the number of nonzeros in the row
512: .  cols - if not `NULL`, the column numbers
513: -  vals - if not `NULL`, the values

515:    Level: advanced

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

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

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

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

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

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

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

543:    Fortran Note:
544:    The calling sequence is
545: .vb
546:    MatGetRow(matrix,row,ncols,cols,values,ierr)
547:          Mat     matrix (input)
548:          integer row    (input)
549:          integer ncols  (output)
550:          integer cols(maxcols) (output)
551:          double precision (or double complex) values(maxcols) output
552: .ve
553:    where maxcols >= maximum nonzeros in any row of the matrix.

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

559: .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
560: @*/
561: PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
562: {
563:   PetscInt incols;

565:   PetscFunctionBegin;
568:   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
569:   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
570:   MatCheckPreallocated(mat, 1);
571:   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
572:   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
573:   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
574:   if (ncols) *ncols = incols;
575:   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
576:   PetscFunctionReturn(PETSC_SUCCESS);
577: }

579: /*@
580:    MatConjugate - replaces the matrix values with their complex conjugates

582:    Logically Collective

584:    Input Parameters:
585: .  mat - the matrix

587:    Level: advanced

589: .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
590: @*/
591: PetscErrorCode MatConjugate(Mat mat)
592: {
593:   PetscFunctionBegin;
595:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
596:   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
597:     PetscUseTypeMethod(mat, conjugate);
598:     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
599:   }
600:   PetscFunctionReturn(PETSC_SUCCESS);
601: }

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

606:    Not Collective

608:    Input Parameters:
609: +  mat - the matrix
610: .  row - the row to get
611: .  ncols, cols - the number of nonzeros and their columns
612: -  vals - if nonzero the column values

614:    Level: advanced

616:    Notes:
617:    This routine should be called after you have finished examining the entries.

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

623:    Fortran Notes:
624:    The calling sequence is
625: .vb
626:    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
627:       Mat     matrix (input)
628:       integer row    (input)
629:       integer ncols  (output)
630:       integer cols(maxcols) (output)
631:       double precision (or double complex) values(maxcols) output
632: .ve
633:    Where maxcols >= maximum nonzeros in any row of the matrix.

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

638: .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`
639: @*/
640: PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
641: {
642:   PetscFunctionBegin;
645:   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
646:   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
647:   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
648:   if (ncols) *ncols = 0;
649:   if (cols) *cols = NULL;
650:   if (vals) *vals = NULL;
651:   PetscFunctionReturn(PETSC_SUCCESS);
652: }

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

658:    Not Collective

660:    Input Parameters:
661: .  mat - the matrix

663:    Level: advanced

665:    Note:
666:    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.

668: .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
669: @*/
670: PetscErrorCode MatGetRowUpperTriangular(Mat mat)
671: {
672:   PetscFunctionBegin;
675:   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
676:   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
677:   MatCheckPreallocated(mat, 1);
678:   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
679:   PetscUseTypeMethod(mat, getrowuppertriangular);
680:   PetscFunctionReturn(PETSC_SUCCESS);
681: }

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

686:    Not Collective

688:    Input Parameters:
689: .  mat - the matrix

691:    Level: advanced

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

696: .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
697: @*/
698: PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
699: {
700:   PetscFunctionBegin;
703:   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
704:   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
705:   MatCheckPreallocated(mat, 1);
706:   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
707:   PetscUseTypeMethod(mat, restorerowuppertriangular);
708:   PetscFunctionReturn(PETSC_SUCCESS);
709: }

711: /*@C
712:    MatSetOptionsPrefix - Sets the prefix used for searching for all
713:    `Mat` options in the database.

715:    Logically Collective

717:    Input Parameters:
718: +  A - the matrix
719: -  prefix - the prefix to prepend to all option names

721:    Level: advanced

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

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

731: .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
732: @*/
733: PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
734: {
735:   PetscFunctionBegin;
737:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
738:   PetscFunctionReturn(PETSC_SUCCESS);
739: }

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

745:    Logically Collective

747:    Input Parameters:
748: +  A - the matrix
749: -  prefix - the prefix to prepend to all option names for the factored matrix

751:    Level: developer

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

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

760: .seealso: [](chapter_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
761: @*/
762: PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
763: {
764:   PetscFunctionBegin;
766:   if (prefix) {
768:     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
769:     if (prefix != A->factorprefix) {
770:       PetscCall(PetscFree(A->factorprefix));
771:       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
772:     }
773:   } else PetscCall(PetscFree(A->factorprefix));
774:   PetscFunctionReturn(PETSC_SUCCESS);
775: }

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

781:    Logically Collective

783:    Input Parameters:
784: +  A - the matrix
785: -  prefix - the prefix to prepend to all option names for the factored matrix

787:    Level: developer

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

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

796: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
797:           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
798:           `MatSetOptionsPrefix()`
799: @*/
800: PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
801: {
802:   char  *buf = A->factorprefix;
803:   size_t len1, len2;

805:   PetscFunctionBegin;
807:   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
808:   if (!buf) {
809:     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
810:     PetscFunctionReturn(PETSC_SUCCESS);
811:   }
812:   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");

814:   PetscCall(PetscStrlen(prefix, &len1));
815:   PetscCall(PetscStrlen(buf, &len2));
816:   PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix));
817:   PetscCall(PetscStrcpy(A->factorprefix, buf));
818:   PetscCall(PetscStrcat(A->factorprefix, prefix));
819:   PetscCall(PetscFree(buf));
820:   PetscFunctionReturn(PETSC_SUCCESS);
821: }

823: /*@C
824:    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
825:    matrix options in the database.

827:    Logically Collective

829:    Input Parameters:
830: +  A - the matrix
831: -  prefix - the prefix to prepend to all option names

833:    Level: advanced

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

839: .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
840: @*/
841: PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
842: {
843:   PetscFunctionBegin;
845:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
846:   PetscFunctionReturn(PETSC_SUCCESS);
847: }

849: /*@C
850:    MatGetOptionsPrefix - Gets the prefix used for searching for all
851:    matrix options in the database.

853:    Not Collective

855:    Input Parameter:
856: .  A - the matrix

858:    Output Parameter:
859: .  prefix - pointer to the prefix string used

861:    Level: advanced

863:    Fortran Note:
864:    The user should pass in a string `prefix` of
865:    sufficient length to hold the prefix.

867: .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
868: @*/
869: PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
870: {
871:   PetscFunctionBegin;
874:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
875:   PetscFunctionReturn(PETSC_SUCCESS);
876: }

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

881:    Collective

883:    Input Parameters:
884: .  A - the matrix

886:    Level: beginner

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

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

893:    Currently only supported for  `MATAIJ` matrices.

895: .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
896: @*/
897: PetscErrorCode MatResetPreallocation(Mat A)
898: {
899:   PetscFunctionBegin;
902:   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
903:   PetscFunctionReturn(PETSC_SUCCESS);
904: }

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

909:    Collective

911:    Input Parameters:
912: .  A - the matrix

914:    Level: intermediate

916:    Notes:
917:    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
918:    setting values in the matrix.

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

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

924: .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
925: @*/
926: PetscErrorCode MatSetUp(Mat A)
927: {
928:   PetscFunctionBegin;
930:   if (!((PetscObject)A)->type_name) {
931:     PetscMPIInt size;

933:     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
934:     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
935:   }
936:   if (!A->preallocated) PetscTryTypeMethod(A, setup);
937:   PetscCall(PetscLayoutSetUp(A->rmap));
938:   PetscCall(PetscLayoutSetUp(A->cmap));
939:   A->preallocated = PETSC_TRUE;
940:   PetscFunctionReturn(PETSC_SUCCESS);
941: }

943: #if defined(PETSC_HAVE_SAWS)
944: #include <petscviewersaws.h>
945: #endif

947: /*@C
948:    MatViewFromOptions - View properties of the matrix based on options set in the options database

950:    Collective

952:    Input Parameters:
953: +  A - the matrix
954: .  obj - optional additional object that provides the options prefix to use
955: -  name - command line option

957:   Options Database Key:
958: .  -mat_view [viewertype]:... - the viewer and its options

960:    Level: intermediate

962:   Notes:
963: .vb
964:     If no value is provided ascii:stdout is used
965:        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
966:                                                   for example ascii::ascii_info prints just the information about the object not all details
967:                                                   unless :append is given filename opens in write mode, overwriting what was already there
968:        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
969:        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
970:        socket[:port]                             defaults to the standard output port
971:        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
972: .ve

974: .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
975: @*/
976: PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
977: {
978:   PetscFunctionBegin;
980:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
981:   PetscFunctionReturn(PETSC_SUCCESS);
982: }

984: /*@C
985:    MatView - display information about a matrix in a variety ways

987:    Collective

989:    Input Parameters:
990: +  mat - the matrix
991: -  viewer - visualization context

993:   Notes:
994:   The available visualization contexts include
995: +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
996: .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
997: .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
998: -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure

1000:    The user can open alternative visualization contexts with
1001: +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1002: .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1003:          specified file; corresponding input uses MatLoad()
1004: .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1005:          an X window display
1006: -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1007:          Currently only the sequential dense and AIJ
1008:          matrix types support the Socket viewer.

1010:    The user can call `PetscViewerPushFormat()` to specify the output
1011:    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1012:    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1013: +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1014: .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1015: .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1016: .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1017:          format common among all matrix types
1018: .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1019:          format (which is in many cases the same as the default)
1020: .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1021:          size and structure (not the matrix entries)
1022: -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1023:          the matrix structure

1025:    Options Database Keys:
1026: +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1027: .  -mat_view ::ascii_info_detail - Prints more detailed info
1028: .  -mat_view - Prints matrix in ASCII format
1029: .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1030: .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1031: .  -display <name> - Sets display name (default is host)
1032: .  -draw_pause <sec> - Sets number of seconds to pause after display
1033: .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1034: .  -viewer_socket_machine <machine> -
1035: .  -viewer_socket_port <port> -
1036: .  -mat_view binary - save matrix to file in binary format
1037: -  -viewer_binary_filename <name> -

1039:    Level: beginner

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

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

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

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

1053:       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1054:       and then use the following mouse functions.
1055: .vb
1056:   left mouse: zoom in
1057:   middle mouse: zoom out
1058:   right mouse: continue with the simulation
1059: .ve

1061: .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1062:           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1063: @*/
1064: PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1065: {
1066:   PetscInt          rows, cols, rbs, cbs;
1067:   PetscBool         isascii, isstring, issaws;
1068:   PetscViewerFormat format;
1069:   PetscMPIInt       size;

1071:   PetscFunctionBegin;
1074:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1076:   PetscCheckSameComm(mat, 1, viewer, 2);

1078:   PetscCall(PetscViewerGetFormat(viewer, &format));
1079:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1080:   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);

1082:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1083:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1084:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1085:   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");

1087:   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1088:   if (isascii) {
1089:     if (!mat->preallocated) {
1090:       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1091:       PetscFunctionReturn(PETSC_SUCCESS);
1092:     }
1093:     if (!mat->assembled) {
1094:       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1095:       PetscFunctionReturn(PETSC_SUCCESS);
1096:     }
1097:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1098:     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1099:       MatNullSpace nullsp, transnullsp;

1101:       PetscCall(PetscViewerASCIIPushTab(viewer));
1102:       PetscCall(MatGetSize(mat, &rows, &cols));
1103:       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1104:       if (rbs != 1 || cbs != 1) {
1105:         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1106:         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1107:       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1108:       if (mat->factortype) {
1109:         MatSolverType solver;
1110:         PetscCall(MatFactorGetSolverType(mat, &solver));
1111:         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1112:       }
1113:       if (mat->ops->getinfo) {
1114:         MatInfo info;
1115:         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1116:         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1117:         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1118:       }
1119:       PetscCall(MatGetNullSpace(mat, &nullsp));
1120:       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1121:       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1122:       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1123:       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1124:       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1125:       PetscCall(PetscViewerASCIIPushTab(viewer));
1126:       PetscCall(MatProductView(mat, viewer));
1127:       PetscCall(PetscViewerASCIIPopTab(viewer));
1128:     }
1129:   } else if (issaws) {
1130: #if defined(PETSC_HAVE_SAWS)
1131:     PetscMPIInt rank;

1133:     PetscCall(PetscObjectName((PetscObject)mat));
1134:     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1135:     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1136: #endif
1137:   } else if (isstring) {
1138:     const char *type;
1139:     PetscCall(MatGetType(mat, &type));
1140:     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1141:     PetscTryTypeMethod(mat, view, viewer);
1142:   }
1143:   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1144:     PetscCall(PetscViewerASCIIPushTab(viewer));
1145:     PetscUseTypeMethod(mat, viewnative, viewer);
1146:     PetscCall(PetscViewerASCIIPopTab(viewer));
1147:   } else if (mat->ops->view) {
1148:     PetscCall(PetscViewerASCIIPushTab(viewer));
1149:     PetscUseTypeMethod(mat, view, viewer);
1150:     PetscCall(PetscViewerASCIIPopTab(viewer));
1151:   }
1152:   if (isascii) {
1153:     PetscCall(PetscViewerGetFormat(viewer, &format));
1154:     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1155:   }
1156:   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1157:   PetscFunctionReturn(PETSC_SUCCESS);
1158: }

1160: #if defined(PETSC_USE_DEBUG)
1161: #include <../src/sys/totalview/tv_data_display.h>
1162: PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1163: {
1164:   TV_add_row("Local rows", "int", &mat->rmap->n);
1165:   TV_add_row("Local columns", "int", &mat->cmap->n);
1166:   TV_add_row("Global rows", "int", &mat->rmap->N);
1167:   TV_add_row("Global columns", "int", &mat->cmap->N);
1168:   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1169:   return TV_format_OK;
1170: }
1171: #endif

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

1179:    Collective

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

1186:    Options Database Keys:
1187:    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1188:    block size
1189: .    -matload_block_size <bs> - set block size

1191:    Level: beginner

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

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

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

1206:    In parallel, each processor can load a subset of rows (or the
1207:    entire matrix).  This routine is especially useful when a large
1208:    matrix is stored on disk and only part of it is desired on each
1209:    processor.  For example, a parallel solver may access only some of
1210:    the rows from each processor.  The algorithm used here reads
1211:    relatively small blocks of data rather than reading the entire
1212:    matrix and then subsetting it.

1214:    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1215:    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1216:    or the sequence like
1217: .vb
1218:     `PetscViewer` v;
1219:     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1220:     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1221:     `PetscViewerSetFromOptions`(v);
1222:     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1223:     `PetscViewerFileSetName`(v,"datafile");
1224: .ve
1225:    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1226: $ -viewer_type {binary,hdf5}

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

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

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

1242: .vb
1243:     PetscInt    MAT_FILE_CLASSID
1244:     PetscInt    number of rows
1245:     PetscInt    number of columns
1246:     PetscInt    total number of nonzeros
1247:     PetscInt    *number nonzeros in each row
1248:     PetscInt    *column indices of all nonzeros (starting index is zero)
1249:     PetscScalar *values of all nonzeros
1250: .ve

1252:    PETSc automatically does the byte swapping for
1253: machines that store the bytes reversed. Thus if you write your own binary
1254: read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1255: and `PetscBinaryWrite()` to see how this may be done.

1257:    Notes:
1258:    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1259:    Each processor's chunk is loaded independently by its owning rank.
1260:    Multiple objects, both matrices and vectors, can be stored within the same file.
1261:    They are looked up by their PetscObject name.

1263:    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1264:    by default the same structure and naming of the AIJ arrays and column count
1265:    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1266: $    save example.mat A b -v7.3
1267:    can be directly read by this routine (see Reference 1 for details).

1269:    Depending on your MATLAB version, this format might be a default,
1270:    otherwise you can set it as default in Preferences.

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

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

1277:    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`

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

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

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

1290: .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1291:  @*/
1292: PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1293: {
1294:   PetscBool flg;

1296:   PetscFunctionBegin;

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

1302:   flg = PETSC_FALSE;
1303:   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1304:   if (flg) {
1305:     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1306:     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1307:   }
1308:   flg = PETSC_FALSE;
1309:   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1310:   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));

1312:   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1313:   PetscUseTypeMethod(mat, load, viewer);
1314:   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1315:   PetscFunctionReturn(PETSC_SUCCESS);
1316: }

1318: static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1319: {
1320:   Mat_Redundant *redund = *redundant;

1322:   PetscFunctionBegin;
1323:   if (redund) {
1324:     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1325:       PetscCall(ISDestroy(&redund->isrow));
1326:       PetscCall(ISDestroy(&redund->iscol));
1327:       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1328:     } else {
1329:       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1330:       PetscCall(PetscFree(redund->sbuf_j));
1331:       PetscCall(PetscFree(redund->sbuf_a));
1332:       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1333:         PetscCall(PetscFree(redund->rbuf_j[i]));
1334:         PetscCall(PetscFree(redund->rbuf_a[i]));
1335:       }
1336:       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1337:     }

1339:     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1340:     PetscCall(PetscFree(redund));
1341:   }
1342:   PetscFunctionReturn(PETSC_SUCCESS);
1343: }

1345: /*@C
1346:    MatDestroy - Frees space taken by a matrix.

1348:    Collective

1350:    Input Parameter:
1351: .  A - the matrix

1353:    Level: beginner

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

1361: .seealso: [](chapter_matrices), `Mat`, `MatCreate()`
1362: @*/
1363: PetscErrorCode MatDestroy(Mat *A)
1364: {
1365:   PetscFunctionBegin;
1366:   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1368:   if (--((PetscObject)(*A))->refct > 0) {
1369:     *A = NULL;
1370:     PetscFunctionReturn(PETSC_SUCCESS);
1371:   }

1373:   /* if memory was published with SAWs then destroy it */
1374:   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1375:   PetscTryTypeMethod((*A), destroy);

1377:   PetscCall(PetscFree((*A)->factorprefix));
1378:   PetscCall(PetscFree((*A)->defaultvectype));
1379:   PetscCall(PetscFree((*A)->defaultrandtype));
1380:   PetscCall(PetscFree((*A)->bsizes));
1381:   PetscCall(PetscFree((*A)->solvertype));
1382:   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1383:   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1384:   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1385:   PetscCall(MatProductClear(*A));
1386:   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1387:   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1388:   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1389:   PetscCall(MatDestroy(&(*A)->schur));
1390:   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1391:   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1392:   PetscCall(PetscHeaderDestroy(A));
1393:   PetscFunctionReturn(PETSC_SUCCESS);
1394: }

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

1401:    Not Collective

1403:    Input Parameters:
1404: +  mat - the matrix
1405: .  v - a logically two-dimensional array of values
1406: .  m, idxm - the number of rows and their global indices
1407: .  n, idxn - the number of columns and their global indices
1408: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

1410:    Level: beginner

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

1415:    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1416:    options cannot be mixed without intervening calls to the assembly
1417:    routines.

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

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

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

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

1435: .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1436:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1437: @*/
1438: PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1439: {
1440:   PetscFunctionBeginHot;
1443:   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1446:   MatCheckPreallocated(mat, 1);

1448:   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1449:   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");

1451:   if (PetscDefined(USE_DEBUG)) {
1452:     PetscInt i, j;

1454:     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1455:     for (i = 0; i < m; i++) {
1456:       for (j = 0; j < n; j++) {
1457:         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1458: #if defined(PETSC_USE_COMPLEX)
1459:           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]);
1460: #else
1461:           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]);
1462: #endif
1463:       }
1464:     }
1465:     for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1466:     for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1467:   }

1469:   if (mat->assembled) {
1470:     mat->was_assembled = PETSC_TRUE;
1471:     mat->assembled     = PETSC_FALSE;
1472:   }
1473:   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1474:   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1475:   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1476:   PetscFunctionReturn(PETSC_SUCCESS);
1477: }

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

1484:    Not Collective

1486:    Input Parameters:
1487: +  mat - the matrix
1488: .  v - a logically two-dimensional array of values
1489: .  ism - the rows to provide
1490: .  isn - the columns to provide
1491: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

1493:    Level: beginner

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

1498:    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1499:    options cannot be mixed without intervening calls to the assembly
1500:    routines.

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

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

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

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

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

1520: .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1521:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1522: @*/
1523: PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1524: {
1525:   PetscInt        m, n;
1526:   const PetscInt *rows, *cols;

1528:   PetscFunctionBeginHot;
1530:   PetscCall(ISGetIndices(ism, &rows));
1531:   PetscCall(ISGetIndices(isn, &cols));
1532:   PetscCall(ISGetLocalSize(ism, &m));
1533:   PetscCall(ISGetLocalSize(isn, &n));
1534:   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1535:   PetscCall(ISRestoreIndices(ism, &rows));
1536:   PetscCall(ISRestoreIndices(isn, &cols));
1537:   PetscFunctionReturn(PETSC_SUCCESS);
1538: }

1540: /*@
1541:    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1542:         values into a matrix

1544:    Not Collective

1546:    Input Parameters:
1547: +  mat - the matrix
1548: .  row - the (block) row to set
1549: -  v - a logically two-dimensional array of values

1551:    Level: intermediate

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

1556:    All the nonzeros in the row must be provided

1558:    The matrix must have previously had its column indices set, likely by having been assembled.

1560:    The row must belong to this process

1562: .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1563:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1564: @*/
1565: PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1566: {
1567:   PetscInt globalrow;

1569:   PetscFunctionBegin;
1573:   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1574:   PetscCall(MatSetValuesRow(mat, globalrow, v));
1575:   PetscFunctionReturn(PETSC_SUCCESS);
1576: }

1578: /*@
1579:    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1580:         values into a matrix

1582:    Not Collective

1584:    Input Parameters:
1585: +  mat - the matrix
1586: .  row - the (block) row to set
1587: -  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

1589:    Level: advanced

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

1594:    All the nonzeros in the row must be provided

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

1598:    The row must belong to this process

1600: .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1601:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1602: @*/
1603: PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1604: {
1605:   PetscFunctionBeginHot;
1608:   MatCheckPreallocated(mat, 1);
1610:   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1611:   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1612:   mat->insertmode = INSERT_VALUES;

1614:   if (mat->assembled) {
1615:     mat->was_assembled = PETSC_TRUE;
1616:     mat->assembled     = PETSC_FALSE;
1617:   }
1618:   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1619:   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1620:   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1621:   PetscFunctionReturn(PETSC_SUCCESS);
1622: }

1624: /*@
1625:    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1626:      Using structured grid indexing

1628:    Not Collective

1630:    Input Parameters:
1631: +  mat - the matrix
1632: .  m - number of rows being entered
1633: .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1634: .  n - number of columns being entered
1635: .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1636: .  v - a logically two-dimensional array of values
1637: -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values

1639:    Level: beginner

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

1644:    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1645:    options cannot be mixed without intervening calls to the assembly
1646:    routines.

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

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

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

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

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

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

1669:    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
1670:    a single value per point) you can skip filling those indices.

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

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

1679:    Fortran Note:
1680:    `idxm` and `idxn` should be declared as
1681: $     MatStencil idxm(4,m),idxn(4,n)
1682:    and the values inserted using
1683: .vb
1684:     idxm(MatStencil_i,1) = i
1685:     idxm(MatStencil_j,1) = j
1686:     idxm(MatStencil_k,1) = k
1687:     idxm(MatStencil_c,1) = c
1688:     etc
1689: .ve

1691: .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1692:           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1693: @*/
1694: PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1695: {
1696:   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1697:   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1698:   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);

1700:   PetscFunctionBegin;
1701:   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */

1707:   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1708:     jdxm = buf;
1709:     jdxn = buf + m;
1710:   } else {
1711:     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1712:     jdxm = bufm;
1713:     jdxn = bufn;
1714:   }
1715:   for (i = 0; i < m; i++) {
1716:     for (j = 0; j < 3 - sdim; j++) dxm++;
1717:     tmp = *dxm++ - starts[0];
1718:     for (j = 0; j < dim - 1; j++) {
1719:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1720:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1721:     }
1722:     if (mat->stencil.noc) dxm++;
1723:     jdxm[i] = tmp;
1724:   }
1725:   for (i = 0; i < n; i++) {
1726:     for (j = 0; j < 3 - sdim; j++) dxn++;
1727:     tmp = *dxn++ - starts[0];
1728:     for (j = 0; j < dim - 1; j++) {
1729:       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1730:       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1731:     }
1732:     if (mat->stencil.noc) dxn++;
1733:     jdxn[i] = tmp;
1734:   }
1735:   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1736:   PetscCall(PetscFree2(bufm, bufn));
1737:   PetscFunctionReturn(PETSC_SUCCESS);
1738: }

1740: /*@
1741:    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1742:      Using structured grid indexing

1744:    Not Collective

1746:    Input Parameters:
1747: +  mat - the matrix
1748: .  m - number of rows being entered
1749: .  idxm - grid coordinates for matrix rows being entered
1750: .  n - number of columns being entered
1751: .  idxn - grid coordinates for matrix columns being entered
1752: .  v - a logically two-dimensional array of values
1753: -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values

1755:    Level: beginner

1757:    Notes:
1758:    By default the values, `v`, are row-oriented and unsorted.
1759:    See `MatSetOption()` for other options.

1761:    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1762:    options cannot be mixed without intervening calls to the assembly
1763:    routines.

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

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

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

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

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

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

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

1789:    Fortran Note:
1790:    `idxm` and `idxn` should be declared as
1791: $     MatStencil idxm(4,m),idxn(4,n)
1792:    and the values inserted using
1793: .vb
1794:     idxm(MatStencil_i,1) = i
1795:     idxm(MatStencil_j,1) = j
1796:     idxm(MatStencil_k,1) = k
1797:    etc
1798: .ve

1800: .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1801:           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1802:           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1803: @*/
1804: PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1805: {
1806:   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1807:   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1808:   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);

1810:   PetscFunctionBegin;
1811:   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */

1818:   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1819:     jdxm = buf;
1820:     jdxn = buf + m;
1821:   } else {
1822:     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1823:     jdxm = bufm;
1824:     jdxn = bufn;
1825:   }
1826:   for (i = 0; i < m; i++) {
1827:     for (j = 0; j < 3 - sdim; j++) dxm++;
1828:     tmp = *dxm++ - starts[0];
1829:     for (j = 0; j < sdim - 1; j++) {
1830:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1831:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1832:     }
1833:     dxm++;
1834:     jdxm[i] = tmp;
1835:   }
1836:   for (i = 0; i < n; i++) {
1837:     for (j = 0; j < 3 - sdim; j++) dxn++;
1838:     tmp = *dxn++ - starts[0];
1839:     for (j = 0; j < sdim - 1; j++) {
1840:       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1841:       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1842:     }
1843:     dxn++;
1844:     jdxn[i] = tmp;
1845:   }
1846:   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1847:   PetscCall(PetscFree2(bufm, bufn));
1848:   PetscFunctionReturn(PETSC_SUCCESS);
1849: }

1851: /*@
1852:    MatSetStencil - Sets the grid information for setting values into a matrix via
1853:         `MatSetValuesStencil()`

1855:    Not Collective

1857:    Input Parameters:
1858: +  mat - the matrix
1859: .  dim - dimension of the grid 1, 2, or 3
1860: .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1861: .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1862: -  dof - number of degrees of freedom per node

1864:    Level: beginner

1866:    Notes:
1867:    Inspired by the structured grid interface to the HYPRE package
1868:    (www.llnl.gov/CASC/hyper)

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

1873: .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1874:           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1875: @*/
1876: PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1877: {
1878:   PetscFunctionBegin;

1883:   mat->stencil.dim = dim + (dof > 1);
1884:   for (PetscInt i = 0; i < dim; i++) {
1885:     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1886:     mat->stencil.starts[i] = starts[dim - i - 1];
1887:   }
1888:   mat->stencil.dims[dim]   = dof;
1889:   mat->stencil.starts[dim] = 0;
1890:   mat->stencil.noc         = (PetscBool)(dof == 1);
1891:   PetscFunctionReturn(PETSC_SUCCESS);
1892: }

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

1897:    Not Collective

1899:    Input Parameters:
1900: +  mat - the matrix
1901: .  v - a logically two-dimensional array of values
1902: .  m  - the number of block rows
1903: .  idxm - the global block indices
1904: .  n - the number of block columns
1905: .  idxn - the global block indices
1906: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values

1908:    Level: intermediate

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

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

1920:    You must call `MatSetBlockSize()` when constructing this matrix (before
1921:    preallocating it).

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

1926:    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1927:    options cannot be mixed without intervening calls to the assembly
1928:    routines.

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

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

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

1944:    Example:
1945: .vb
1946:    Suppose m=n=2 and block size(bs) = 2 The array is

1948:    1  2  | 3  4
1949:    5  6  | 7  8
1950:    - - - | - - -
1951:    9  10 | 11 12
1952:    13 14 | 15 16

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

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

1961: .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1962: @*/
1963: PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1964: {
1965:   PetscFunctionBeginHot;
1968:   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1971:   MatCheckPreallocated(mat, 1);
1972:   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1973:   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1974:   if (PetscDefined(USE_DEBUG)) {
1975:     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1976:     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1977:   }
1978:   if (PetscDefined(USE_DEBUG)) {
1979:     PetscInt rbs, cbs, M, N, i;
1980:     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1981:     PetscCall(MatGetSize(mat, &M, &N));
1982:     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M);
1983:     for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N);
1984:   }
1985:   if (mat->assembled) {
1986:     mat->was_assembled = PETSC_TRUE;
1987:     mat->assembled     = PETSC_FALSE;
1988:   }
1989:   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1990:   if (mat->ops->setvaluesblocked) {
1991:     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1992:   } else {
1993:     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1994:     PetscInt i, j, bs, cbs;

1996:     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1997:     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1998:       iidxm = buf;
1999:       iidxn = buf + m * bs;
2000:     } else {
2001:       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2002:       iidxm = bufr;
2003:       iidxn = bufc;
2004:     }
2005:     for (i = 0; i < m; i++) {
2006:       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2007:     }
2008:     if (m != n || bs != cbs || idxm != idxn) {
2009:       for (i = 0; i < n; i++) {
2010:         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2011:       }
2012:     } else iidxn = iidxm;
2013:     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2014:     PetscCall(PetscFree2(bufr, bufc));
2015:   }
2016:   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2017:   PetscFunctionReturn(PETSC_SUCCESS);
2018: }

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

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

2025:    Input Parameters:
2026: +  mat - the matrix
2027: .  v - a logically two-dimensional array for storing the values
2028: .  m  - the number of rows
2029: .  idxm - the  global indices of the rows
2030: .  n - the number of columns
2031: -  idxn - the global indices of the columns

2033:    Level: advanced

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

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

2043:      `MatGetValues()` requires that the matrix has been assembled
2044:      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2045:      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2046:      without intermediate matrix assembly.

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

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

2055: .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2056: @*/
2057: PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2058: {
2059:   PetscFunctionBegin;
2062:   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2066:   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2067:   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2068:   MatCheckPreallocated(mat, 1);

2070:   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2071:   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2072:   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2073:   PetscFunctionReturn(PETSC_SUCCESS);
2074: }

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

2080:    Not Collective

2082:    Input Parameters:
2083: +  mat - the matrix
2084: .  nrow - number of rows
2085: .  irow - the row local indices
2086: .  ncol - number of columns
2087: -  icol - the column local indices

2089:    Output Parameter:
2090: .  y -  a logically two-dimensional array of values

2092:    Level: advanced

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

2097:      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,
2098:      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2099:      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2100:      with `MatSetLocalToGlobalMapping()`.

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

2106: .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2107:           `MatSetValuesLocal()`, `MatGetValues()`
2108: @*/
2109: PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2110: {
2111:   PetscFunctionBeginHot;
2114:   MatCheckPreallocated(mat, 1);
2115:   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2118:   if (PetscDefined(USE_DEBUG)) {
2119:     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2120:     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2121:   }
2122:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2123:   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2124:   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2125:   else {
2126:     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2127:     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2128:       irowm = buf;
2129:       icolm = buf + nrow;
2130:     } else {
2131:       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2132:       irowm = bufr;
2133:       icolm = bufc;
2134:     }
2135:     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2136:     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2137:     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2138:     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2139:     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2140:     PetscCall(PetscFree2(bufr, bufc));
2141:   }
2142:   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2143:   PetscFunctionReturn(PETSC_SUCCESS);
2144: }

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

2150:   Not Collective

2152:   Input Parameters:
2153: + mat - the matrix
2154: . nb - the number of blocks
2155: . bs - the number of rows (and columns) in each block
2156: . rows - a concatenation of the rows for each block
2157: - v - a concatenation of logically two-dimensional arrays of values

2159:   Level: advanced

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

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

2166: .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2167:           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2168: @*/
2169: PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2170: {
2171:   PetscFunctionBegin;
2176:   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");

2178:   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2179:   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2180:   else {
2181:     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2182:   }
2183:   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2184:   PetscFunctionReturn(PETSC_SUCCESS);
2185: }

2187: /*@
2188:    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2189:    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2190:    using a local (per-processor) numbering.

2192:    Not Collective

2194:    Input Parameters:
2195: +  x - the matrix
2196: .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2197: -  cmapping - column mapping

2199:    Level: intermediate

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

2204: .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2205: @*/
2206: PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2207: {
2208:   PetscFunctionBegin;
2213:   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2214:   else {
2215:     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2216:     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2217:   }
2218:   PetscFunctionReturn(PETSC_SUCCESS);
2219: }

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

2224:    Not Collective

2226:    Input Parameter:
2227: .  A - the matrix

2229:    Output Parameters:
2230: + rmapping - row mapping
2231: - cmapping - column mapping

2233:    Level: advanced

2235: .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2236: @*/
2237: PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2238: {
2239:   PetscFunctionBegin;
2242:   if (rmapping) {
2244:     *rmapping = A->rmap->mapping;
2245:   }
2246:   if (cmapping) {
2248:     *cmapping = A->cmap->mapping;
2249:   }
2250:   PetscFunctionReturn(PETSC_SUCCESS);
2251: }

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

2256:    Logically Collective

2258:    Input Parameters:
2259: +  A - the matrix
2260: . rmap - row layout
2261: - cmap - column layout

2263:    Level: advanced

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

2268: .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2269: @*/
2270: PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2271: {
2272:   PetscFunctionBegin;
2274:   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2275:   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2276:   PetscFunctionReturn(PETSC_SUCCESS);
2277: }

2279: /*@
2280:    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns

2282:    Not Collective

2284:    Input Parameter:
2285: .  A - the matrix

2287:    Output Parameters:
2288: + rmap - row layout
2289: - cmap - column layout

2291:    Level: advanced

2293: .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2294: @*/
2295: PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2296: {
2297:   PetscFunctionBegin;
2300:   if (rmap) {
2302:     *rmap = A->rmap;
2303:   }
2304:   if (cmap) {
2306:     *cmap = A->cmap;
2307:   }
2308:   PetscFunctionReturn(PETSC_SUCCESS);
2309: }

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

2315:    Not Collective

2317:    Input Parameters:
2318: +  mat - the matrix
2319: .  nrow - number of rows
2320: .  irow - the row local indices
2321: .  ncol - number of columns
2322: .  icol - the column local indices
2323: .  y -  a logically two-dimensional array of values
2324: -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

2326:    Level: intermediate

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

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

2334:    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2335:    options cannot be mixed without intervening calls to the assembly
2336:    routines.

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

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

2345: .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2346:           `MatGetValuesLocal()`
2347: @*/
2348: PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2349: {
2350:   PetscFunctionBeginHot;
2353:   MatCheckPreallocated(mat, 1);
2354:   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2357:   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2358:   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2359:   if (PetscDefined(USE_DEBUG)) {
2360:     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2361:     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2362:   }

2364:   if (mat->assembled) {
2365:     mat->was_assembled = PETSC_TRUE;
2366:     mat->assembled     = PETSC_FALSE;
2367:   }
2368:   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2369:   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2370:   else {
2371:     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2372:     const PetscInt *irowm, *icolm;

2374:     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2375:       bufr  = buf;
2376:       bufc  = buf + nrow;
2377:       irowm = bufr;
2378:       icolm = bufc;
2379:     } else {
2380:       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2381:       irowm = bufr;
2382:       icolm = bufc;
2383:     }
2384:     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2385:     else irowm = irow;
2386:     if (mat->cmap->mapping) {
2387:       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2388:         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2389:       } else icolm = irowm;
2390:     } else icolm = icol;
2391:     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2392:     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2393:   }
2394:   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2395:   PetscFunctionReturn(PETSC_SUCCESS);
2396: }

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

2402:    Not Collective

2404:    Input Parameters:
2405: +  x - the matrix
2406: .  nrow - number of rows
2407: .  irow - the row local indices
2408: .  ncol - number of columns
2409: .  icol - the column local indices
2410: .  y -  a logically two-dimensional array of values
2411: -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values

2413:    Level: intermediate

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

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

2422:    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2423:    options cannot be mixed without intervening calls to the assembly
2424:    routines.

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

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

2433: .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2434:           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2435: @*/
2436: PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2437: {
2438:   PetscFunctionBeginHot;
2441:   MatCheckPreallocated(mat, 1);
2442:   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2445:   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2446:   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2447:   if (PetscDefined(USE_DEBUG)) {
2448:     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2449:     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2450:   }

2452:   if (mat->assembled) {
2453:     mat->was_assembled = PETSC_TRUE;
2454:     mat->assembled     = PETSC_FALSE;
2455:   }
2456:   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2457:     PetscInt irbs, rbs;
2458:     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2459:     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2460:     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2461:   }
2462:   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2463:     PetscInt icbs, cbs;
2464:     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2465:     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2466:     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2467:   }
2468:   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2469:   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2470:   else {
2471:     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2472:     const PetscInt *irowm, *icolm;

2474:     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2475:       bufr  = buf;
2476:       bufc  = buf + nrow;
2477:       irowm = bufr;
2478:       icolm = bufc;
2479:     } else {
2480:       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2481:       irowm = bufr;
2482:       icolm = bufc;
2483:     }
2484:     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2485:     else irowm = irow;
2486:     if (mat->cmap->mapping) {
2487:       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2488:         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2489:       } else icolm = irowm;
2490:     } else icolm = icol;
2491:     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2492:     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2493:   }
2494:   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2495:   PetscFunctionReturn(PETSC_SUCCESS);
2496: }

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

2501:    Collective

2503:    Input Parameters:
2504: +  mat - the matrix
2505: -  x   - the vector to be multiplied

2507:    Output Parameters:
2508: .  y - the result

2510:    Level: developer

2512:    Note:
2513:    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2514:    call `MatMultDiagonalBlock`(A,y,y).

2516: .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2517: @*/
2518: PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2519: {
2520:   PetscFunctionBegin;

2526:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2527:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2528:   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2529:   MatCheckPreallocated(mat, 1);

2531:   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2532:   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2533:   PetscFunctionReturn(PETSC_SUCCESS);
2534: }

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

2539:    Neighbor-wise Collective

2541:    Input Parameters:
2542: +  mat - the matrix
2543: -  x   - the vector to be multiplied

2545:    Output Parameters:
2546: .  y - the result

2548:    Level: beginner

2550:    Note:
2551:    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2552:    call `MatMult`(A,y,y).

2554: .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2555: @*/
2556: PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2557: {
2558:   PetscFunctionBegin;
2562:   VecCheckAssembled(x);
2564:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2565:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2566:   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2567:   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
2568:   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
2569:   PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n);
2570:   PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n);
2571:   PetscCall(VecSetErrorIfLocked(y, 3));
2572:   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2573:   MatCheckPreallocated(mat, 1);

2575:   PetscCall(VecLockReadPush(x));
2576:   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2577:   PetscUseTypeMethod(mat, mult, x, y);
2578:   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2579:   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2580:   PetscCall(VecLockReadPop(x));
2581:   PetscFunctionReturn(PETSC_SUCCESS);
2582: }

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

2587:    Neighbor-wise Collective

2589:    Input Parameters:
2590: +  mat - the matrix
2591: -  x   - the vector to be multiplied

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

2596:    Level: beginner

2598:    Notes:
2599:    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2600:    call `MatMultTranspose`(A,y,y).

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

2605: .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2606: @*/
2607: PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2608: {
2609:   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;

2611:   PetscFunctionBegin;
2615:   VecCheckAssembled(x);

2618:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2619:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2620:   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2621:   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2622:   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2623:   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2624:   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2625:   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2626:   MatCheckPreallocated(mat, 1);

2628:   if (!mat->ops->multtranspose) {
2629:     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2630:     PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name);
2631:   } else op = mat->ops->multtranspose;
2632:   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2633:   PetscCall(VecLockReadPush(x));
2634:   PetscCall((*op)(mat, x, y));
2635:   PetscCall(VecLockReadPop(x));
2636:   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2637:   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2638:   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2639:   PetscFunctionReturn(PETSC_SUCCESS);
2640: }

2642: /*@
2643:    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.

2645:    Neighbor-wise Collective

2647:    Input Parameters:
2648: +  mat - the matrix
2649: -  x   - the vector to be multilplied

2651:    Output Parameters:
2652: .  y - the result

2654:    Level: beginner

2656:    Notes:
2657:    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2658:    call `MatMultHermitianTranspose`(A,y,y).

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

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

2664: .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2665: @*/
2666: PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2667: {
2668:   PetscFunctionBegin;

2674:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2675:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2676:   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2677:   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2678:   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2679:   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2680:   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2681:   MatCheckPreallocated(mat, 1);

2683:   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2684: #if defined(PETSC_USE_COMPLEX)
2685:   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2686:     PetscCall(VecLockReadPush(x));
2687:     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2688:     else PetscUseTypeMethod(mat, mult, x, y);
2689:     PetscCall(VecLockReadPop(x));
2690:   } else {
2691:     Vec w;
2692:     PetscCall(VecDuplicate(x, &w));
2693:     PetscCall(VecCopy(x, w));
2694:     PetscCall(VecConjugate(w));
2695:     PetscCall(MatMultTranspose(mat, w, y));
2696:     PetscCall(VecDestroy(&w));
2697:     PetscCall(VecConjugate(y));
2698:   }
2699:   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2700: #else
2701:   PetscCall(MatMultTranspose(mat, x, y));
2702: #endif
2703:   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2704:   PetscFunctionReturn(PETSC_SUCCESS);
2705: }

2707: /*@
2708:     MatMultAdd -  Computes v3 = v2 + A * v1.

2710:     Neighbor-wise Collective

2712:     Input Parameters:
2713: +   mat - the matrix
2714: -   v1, v2 - the vectors

2716:     Output Parameters:
2717: .   v3 - the result

2719:     Level: beginner

2721:     Note:
2722:     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2723:     call `MatMultAdd`(A,v1,v2,v1).

2725: .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2726: @*/
2727: PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2728: {
2729:   PetscFunctionBegin;

2736:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2737:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2738:   PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N);
2739:   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2740:      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2741:   PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n);
2742:   PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n);
2743:   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2744:   MatCheckPreallocated(mat, 1);

2746:   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2747:   PetscCall(VecLockReadPush(v1));
2748:   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2749:   PetscCall(VecLockReadPop(v1));
2750:   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2751:   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2752:   PetscFunctionReturn(PETSC_SUCCESS);
2753: }

2755: /*@
2756:    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.

2758:    Neighbor-wise Collective

2760:    Input Parameters:
2761: +  mat - the matrix
2762: -  v1, v2 - the vectors

2764:    Output Parameters:
2765: .  v3 - the result

2767:    Level: beginner

2769:    Note:
2770:    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2771:    call `MatMultTransposeAdd`(A,v1,v2,v1).

2773: .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2774: @*/
2775: PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2776: {
2777:   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;

2779:   PetscFunctionBegin;

2786:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2787:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2788:   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2789:   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2790:   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2791:   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2792:   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2793:   MatCheckPreallocated(mat, 1);

2795:   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2796:   PetscCall(VecLockReadPush(v1));
2797:   PetscCall((*op)(mat, v1, v2, v3));
2798:   PetscCall(VecLockReadPop(v1));
2799:   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2800:   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2801:   PetscFunctionReturn(PETSC_SUCCESS);
2802: }

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

2807:    Neighbor-wise Collective

2809:    Input Parameters:
2810: +  mat - the matrix
2811: -  v1, v2 - the vectors

2813:    Output Parameters:
2814: .  v3 - the result

2816:    Level: beginner

2818:    Note:
2819:    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2820:    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).

2822: .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2823: @*/
2824: PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2825: {
2826:   PetscFunctionBegin;

2833:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2834:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2835:   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2836:   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2837:   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2838:   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2839:   MatCheckPreallocated(mat, 1);

2841:   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2842:   PetscCall(VecLockReadPush(v1));
2843:   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2844:   else {
2845:     Vec w, z;
2846:     PetscCall(VecDuplicate(v1, &w));
2847:     PetscCall(VecCopy(v1, w));
2848:     PetscCall(VecConjugate(w));
2849:     PetscCall(VecDuplicate(v3, &z));
2850:     PetscCall(MatMultTranspose(mat, w, z));
2851:     PetscCall(VecDestroy(&w));
2852:     PetscCall(VecConjugate(z));
2853:     if (v2 != v3) {
2854:       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2855:     } else {
2856:       PetscCall(VecAXPY(v3, 1.0, z));
2857:     }
2858:     PetscCall(VecDestroy(&z));
2859:   }
2860:   PetscCall(VecLockReadPop(v1));
2861:   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2862:   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2863:   PetscFunctionReturn(PETSC_SUCCESS);
2864: }

2866: /*@C
2867:    MatGetFactorType - gets the type of factorization it is

2869:    Not Collective

2871:    Input Parameters:
2872: .  mat - the matrix

2874:    Output Parameters:
2875: .  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`

2877:    Level: intermediate

2879: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2880:           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2881: @*/
2882: PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2883: {
2884:   PetscFunctionBegin;
2888:   *t = mat->factortype;
2889:   PetscFunctionReturn(PETSC_SUCCESS);
2890: }

2892: /*@C
2893:    MatSetFactorType - sets the type of factorization it is

2895:    Logically Collective

2897:    Input Parameters:
2898: +  mat - the matrix
2899: -  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`

2901:    Level: intermediate

2903: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2904:           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2905: @*/
2906: PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2907: {
2908:   PetscFunctionBegin;
2911:   mat->factortype = t;
2912:   PetscFunctionReturn(PETSC_SUCCESS);
2913: }

2915: /*@C
2916:    MatGetInfo - Returns information about matrix storage (number of
2917:    nonzeros, memory, etc.).

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

2921:    Input Parameters:
2922: +  mat - the matrix
2923: -  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)

2925:    Output Parameters:
2926: .  info - matrix information context

2928:    Notes:
2929:    The `MatInfo` context contains a variety of matrix data, including
2930:    number of nonzeros allocated and used, number of mallocs during
2931:    matrix assembly, etc.  Additional information for factored matrices
2932:    is provided (such as the fill ratio, number of mallocs during
2933:    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2934:    when using the runtime options
2935: $       -info -mat_view ::ascii_info

2937:    Example:
2938:    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2939:    data within the MatInfo context.  For example,
2940: .vb
2941:       MatInfo info;
2942:       Mat     A;
2943:       double  mal, nz_a, nz_u;

2945:       MatGetInfo(A,MAT_LOCAL,&info);
2946:       mal  = info.mallocs;
2947:       nz_a = info.nz_allocated;
2948: .ve

2950:    Fortran users should declare info as a double precision
2951:    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2952:    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2953:    a complete list of parameter names.
2954: .vb
2955:       double  precision info(MAT_INFO_SIZE)
2956:       double  precision mal, nz_a
2957:       Mat     A
2958:       integer ierr

2960:       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2961:       mal = info(MAT_INFO_MALLOCS)
2962:       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2963: .ve

2965:     Level: intermediate

2967:     Developer Note:
2968:     The Fortran interface is not autogenerated as the
2969:     interface definition cannot be generated correctly [due to `MatInfo` argument]

2971: .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2972: @*/
2973: PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2974: {
2975:   PetscFunctionBegin;
2979:   MatCheckPreallocated(mat, 1);
2980:   PetscUseTypeMethod(mat, getinfo, flag, info);
2981:   PetscFunctionReturn(PETSC_SUCCESS);
2982: }

2984: /*
2985:    This is used by external packages where it is not easy to get the info from the actual
2986:    matrix factorization.
2987: */
2988: PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2989: {
2990:   PetscFunctionBegin;
2991:   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2992:   PetscFunctionReturn(PETSC_SUCCESS);
2993: }

2995: /*@C
2996:    MatLUFactor - Performs in-place LU factorization of matrix.

2998:    Collective

3000:    Input Parameters:
3001: +  mat - the matrix
3002: .  row - row permutation
3003: .  col - column permutation
3004: -  info - options for factorization, includes
3005: .vb
3006:           fill - expected fill as ratio of original fill.
3007:           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3008:                    Run with the option -info to determine an optimal value to use
3009: .ve
3010:    Level: developer

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

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

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

3023:    Developer Note:
3024:    The Fortran interface is not autogenerated as the
3025:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3027: .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3028:           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3029: @*/
3030: PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3031: {
3032:   MatFactorInfo tinfo;

3034:   PetscFunctionBegin;
3040:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3041:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3042:   MatCheckPreallocated(mat, 1);
3043:   if (!info) {
3044:     PetscCall(MatFactorInfoInitialize(&tinfo));
3045:     info = &tinfo;
3046:   }

3048:   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3049:   PetscUseTypeMethod(mat, lufactor, row, col, info);
3050:   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3051:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3052:   PetscFunctionReturn(PETSC_SUCCESS);
3053: }

3055: /*@C
3056:    MatILUFactor - Performs in-place ILU factorization of matrix.

3058:    Collective

3060:    Input Parameters:
3061: +  mat - the matrix
3062: .  row - row permutation
3063: .  col - column permutation
3064: -  info - structure containing
3065: .vb
3066:       levels - number of levels of fill.
3067:       expected fill - as ratio of original fill.
3068:       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3069:                 missing diagonal entries)
3070: .ve

3072:    Level: developer

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

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

3083:    Developer Note:
3084:    The Fortran interface is not autogenerated as the
3085:    interface definition cannot be generated correctly [due to MatFactorInfo]

3087: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3088: @*/
3089: PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3090: {
3091:   PetscFunctionBegin;
3097:   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3098:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3099:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3100:   MatCheckPreallocated(mat, 1);

3102:   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3103:   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3104:   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3105:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3106:   PetscFunctionReturn(PETSC_SUCCESS);
3107: }

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

3113:    Collective

3115:    Input Parameters:
3116: +  fact - the factor matrix obtained with `MatGetFactor()`
3117: .  mat - the matrix
3118: .  row, col - row and column permutations
3119: -  info - options for factorization, includes
3120: .vb
3121:           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3122:           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3123: .ve

3125:    Level: developer

3127:    Notes:
3128:     See [Matrix Factorization](sec_matfactor) for additional information about factorizations

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

3134:    Developer Note:
3135:    The Fortran interface is not autogenerated as the
3136:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3138: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3139: @*/
3140: PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3141: {
3142:   MatFactorInfo tinfo;

3144:   PetscFunctionBegin;
3151:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3152:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3153:   if (!(fact)->ops->lufactorsymbolic) {
3154:     MatSolverType stype;
3155:     PetscCall(MatFactorGetSolverType(fact, &stype));
3156:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3157:   }
3158:   MatCheckPreallocated(mat, 2);
3159:   if (!info) {
3160:     PetscCall(MatFactorInfoInitialize(&tinfo));
3161:     info = &tinfo;
3162:   }

3164:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3165:   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3166:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3167:   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3168:   PetscFunctionReturn(PETSC_SUCCESS);
3169: }

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

3175:    Collective

3177:    Input Parameters:
3178: +  fact - the factor matrix obtained with `MatGetFactor()`
3179: .  mat - the matrix
3180: -  info - options for factorization

3182:    Level: developer

3184:    Notes:
3185:    See `MatLUFactor()` for in-place factorization.  See
3186:    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.

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

3192:     Developer Note:
3193:     The Fortran interface is not autogenerated as the
3194:     interface definition cannot be generated correctly [due to `MatFactorInfo`]

3196: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3197: @*/
3198: PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3199: {
3200:   MatFactorInfo tinfo;

3202:   PetscFunctionBegin;
3207:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3208:   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3209:              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);

3211:   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3212:   MatCheckPreallocated(mat, 2);
3213:   if (!info) {
3214:     PetscCall(MatFactorInfoInitialize(&tinfo));
3215:     info = &tinfo;
3216:   }

3218:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3219:   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3220:   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3221:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3222:   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3223:   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3224:   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3225:   PetscFunctionReturn(PETSC_SUCCESS);
3226: }

3228: /*@C
3229:    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3230:    symmetric matrix.

3232:    Collective

3234:    Input Parameters:
3235: +  mat - the matrix
3236: .  perm - row and column permutations
3237: -  f - expected fill as ratio of original fill

3239:    Level: developer

3241:    Notes:
3242:    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3243:    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.

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

3249:    Developer Note:
3250:    The Fortran interface is not autogenerated as the
3251:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3253: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3254:           `MatGetOrdering()`
3255: @*/
3256: PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3257: {
3258:   MatFactorInfo tinfo;

3260:   PetscFunctionBegin;
3265:   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3266:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3267:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3268:   MatCheckPreallocated(mat, 1);
3269:   if (!info) {
3270:     PetscCall(MatFactorInfoInitialize(&tinfo));
3271:     info = &tinfo;
3272:   }

3274:   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3275:   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3276:   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3277:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3278:   PetscFunctionReturn(PETSC_SUCCESS);
3279: }

3281: /*@C
3282:    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3283:    of a symmetric matrix.

3285:    Collective

3287:    Input Parameters:
3288: +  fact - the factor matrix obtained with `MatGetFactor()`
3289: .  mat - the matrix
3290: .  perm - row and column permutations
3291: -  info - options for factorization, includes
3292: .vb
3293:           fill - expected fill as ratio of original fill.
3294:           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3295:                    Run with the option -info to determine an optimal value to use
3296: .ve

3298:    Level: developer

3300:    Notes:
3301:    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3302:    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.

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

3308:    Developer Note:
3309:    The Fortran interface is not autogenerated as the
3310:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3312: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3313:           `MatGetOrdering()`
3314: @*/
3315: PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3316: {
3317:   MatFactorInfo tinfo;

3319:   PetscFunctionBegin;
3325:   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3326:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3327:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3328:   if (!(fact)->ops->choleskyfactorsymbolic) {
3329:     MatSolverType stype;
3330:     PetscCall(MatFactorGetSolverType(fact, &stype));
3331:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3332:   }
3333:   MatCheckPreallocated(mat, 2);
3334:   if (!info) {
3335:     PetscCall(MatFactorInfoInitialize(&tinfo));
3336:     info = &tinfo;
3337:   }

3339:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3340:   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3341:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3342:   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3343:   PetscFunctionReturn(PETSC_SUCCESS);
3344: }

3346: /*@C
3347:    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3348:    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3349:    `MatCholeskyFactorSymbolic()`.

3351:    Collective

3353:    Input Parameters:
3354: +  fact - the factor matrix obtained with `MatGetFactor()`
3355: .  mat - the initial matrix
3356: .  info - options for factorization
3357: -  fact - the symbolic factor of mat

3359:    Level: developer

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

3366:    Developer Note:
3367:    The Fortran interface is not autogenerated as the
3368:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3370: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3371: @*/
3372: PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3373: {
3374:   MatFactorInfo tinfo;

3376:   PetscFunctionBegin;
3381:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3382:   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3383:   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3384:              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3385:   MatCheckPreallocated(mat, 2);
3386:   if (!info) {
3387:     PetscCall(MatFactorInfoInitialize(&tinfo));
3388:     info = &tinfo;
3389:   }

3391:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3392:   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3393:   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3394:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3395:   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3396:   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3397:   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3398:   PetscFunctionReturn(PETSC_SUCCESS);
3399: }

3401: /*@
3402:    MatQRFactor - Performs in-place QR factorization of matrix.

3404:    Collective

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

3416:    Level: developer

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

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

3426:    Developer Note:
3427:    The Fortran interface is not autogenerated as the
3428:    interface definition cannot be generated correctly [due to MatFactorInfo]

3430: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3431:           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3432: @*/
3433: PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3434: {
3435:   PetscFunctionBegin;
3440:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3441:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3442:   MatCheckPreallocated(mat, 1);
3443:   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3444:   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3445:   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3446:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3447:   PetscFunctionReturn(PETSC_SUCCESS);
3448: }

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

3454:    Collective

3456:    Input Parameters:
3457: +  fact - the factor matrix obtained with `MatGetFactor()`
3458: .  mat - the matrix
3459: .  col - column permutation
3460: -  info - options for factorization, includes
3461: .vb
3462:           fill - expected fill as ratio of original fill.
3463:           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3464:                    Run with the option -info to determine an optimal value to use
3465: .ve

3467:    Level: developer

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

3474:    Developer Note:
3475:    The Fortran interface is not autogenerated as the
3476:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3478: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3479: @*/
3480: PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3481: {
3482:   MatFactorInfo tinfo;

3484:   PetscFunctionBegin;
3490:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3491:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3492:   MatCheckPreallocated(mat, 2);
3493:   if (!info) {
3494:     PetscCall(MatFactorInfoInitialize(&tinfo));
3495:     info = &tinfo;
3496:   }

3498:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3499:   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3500:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3501:   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3502:   PetscFunctionReturn(PETSC_SUCCESS);
3503: }

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

3509:    Collective

3511:    Input Parameters:
3512: +  fact - the factor matrix obtained with `MatGetFactor()`
3513: .  mat - the matrix
3514: -  info - options for factorization

3516:    Level: developer

3518:    Notes:
3519:    See `MatQRFactor()` for in-place factorization.

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

3525:    Developer Note:
3526:    The Fortran interface is not autogenerated as the
3527:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

3529: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3530: @*/
3531: PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3532: {
3533:   MatFactorInfo tinfo;

3535:   PetscFunctionBegin;
3540:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3541:   PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3542:              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);

3544:   MatCheckPreallocated(mat, 2);
3545:   if (!info) {
3546:     PetscCall(MatFactorInfoInitialize(&tinfo));
3547:     info = &tinfo;
3548:   }

3550:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3551:   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3552:   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3553:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3554:   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3555:   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3556:   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3557:   PetscFunctionReturn(PETSC_SUCCESS);
3558: }

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

3563:    Neighbor-wise Collective

3565:    Input Parameters:
3566: +  mat - the factored matrix
3567: -  b - the right-hand-side vector

3569:    Output Parameter:
3570: .  x - the result vector

3572:    Level: developer

3574:    Notes:
3575:    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3576:    call `MatSolve`(A,x,x).

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

3582: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3583: @*/
3584: PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3585: {
3586:   PetscFunctionBegin;
3591:   PetscCheckSameComm(mat, 1, b, 2);
3592:   PetscCheckSameComm(mat, 1, x, 3);
3593:   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3594:   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3595:   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3596:   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3597:   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3598:   MatCheckPreallocated(mat, 1);

3600:   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3601:   if (mat->factorerrortype) {
3602:     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3603:     PetscCall(VecSetInf(x));
3604:   } else PetscUseTypeMethod(mat, solve, b, x);
3605:   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3606:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3607:   PetscFunctionReturn(PETSC_SUCCESS);
3608: }

3610: static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3611: {
3612:   Vec      b, x;
3613:   PetscInt N, i;
3614:   PetscErrorCode (*f)(Mat, Vec, Vec);
3615:   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;

3617:   PetscFunctionBegin;
3618:   if (A->factorerrortype) {
3619:     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3620:     PetscCall(MatSetInf(X));
3621:     PetscFunctionReturn(PETSC_SUCCESS);
3622:   }
3623:   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3624:   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3625:   PetscCall(MatBoundToCPU(A, &Abound));
3626:   if (!Abound) {
3627:     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3628:     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3629:   }
3630: #if defined(PETSC_HAVE_CUDA)
3631:   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3632:   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3633: #elif (PETSC_HAVE_HIP)
3634:   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3635:   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3636: #endif
3637:   PetscCall(MatGetSize(B, NULL, &N));
3638:   for (i = 0; i < N; i++) {
3639:     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3640:     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3641:     PetscCall((*f)(A, b, x));
3642:     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3643:     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3644:   }
3645:   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3646:   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3647:   PetscFunctionReturn(PETSC_SUCCESS);
3648: }

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

3653:    Neighbor-wise Collective

3655:    Input Parameters:
3656: +  A - the factored matrix
3657: -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)

3659:    Output Parameter:
3660: .  X - the result matrix (dense matrix)

3662:    Level: developer

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

3668: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3669: @*/
3670: PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3671: {
3672:   PetscFunctionBegin;
3677:   PetscCheckSameComm(A, 1, B, 2);
3678:   PetscCheckSameComm(A, 1, X, 3);
3679:   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3680:   PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3681:   PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3682:   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3683:   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3684:   MatCheckPreallocated(A, 1);

3686:   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3687:   if (!A->ops->matsolve) {
3688:     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3689:     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3690:   } else PetscUseTypeMethod(A, matsolve, B, X);
3691:   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3692:   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3693:   PetscFunctionReturn(PETSC_SUCCESS);
3694: }

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

3699:    Neighbor-wise Collective

3701:    Input Parameters:
3702: +  A - the factored matrix
3703: -  B - the right-hand-side matrix  (`MATDENSE` matrix)

3705:    Output Parameter:
3706: .  X - the result matrix (dense matrix)

3708:    Level: developer

3710:    Note:
3711:    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3712:    call `MatMatSolveTranspose`(A,X,X).

3714: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3715: @*/
3716: PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3717: {
3718:   PetscFunctionBegin;
3723:   PetscCheckSameComm(A, 1, B, 2);
3724:   PetscCheckSameComm(A, 1, X, 3);
3725:   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3726:   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3727:   PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3728:   PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n);
3729:   PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3730:   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3731:   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3732:   MatCheckPreallocated(A, 1);

3734:   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3735:   if (!A->ops->matsolvetranspose) {
3736:     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3737:     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3738:   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3739:   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3740:   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3741:   PetscFunctionReturn(PETSC_SUCCESS);
3742: }

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

3747:    Neighbor-wise Collective

3749:    Input Parameters:
3750: +  A - the factored matrix
3751: -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`

3753:    Output Parameter:
3754: .  X - the result matrix (dense matrix)

3756:    Level: developer

3758:    Note:
3759:    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
3760:    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.

3762: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3763: @*/
3764: PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3765: {
3766:   PetscFunctionBegin;
3771:   PetscCheckSameComm(A, 1, Bt, 2);
3772:   PetscCheckSameComm(A, 1, X, 3);

3774:   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3775:   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3776:   PetscCheck(A->rmap->N == Bt->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, Bt->cmap->N);
3777:   PetscCheck(X->cmap->N >= Bt->rmap->N, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as row number of the rhs matrix");
3778:   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3779:   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3780:   MatCheckPreallocated(A, 1);

3782:   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3783:   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3784:   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3785:   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3786:   PetscFunctionReturn(PETSC_SUCCESS);
3787: }

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

3793:    Neighbor-wise Collective

3795:    Input Parameters:
3796: +  mat - the factored matrix
3797: -  b - the right-hand-side vector

3799:    Output Parameter:
3800: .  x - the result vector

3802:    Level: developer

3804:    Notes:
3805:    `MatSolve()` should be used for most applications, as it performs
3806:    a forward solve followed by a backward solve.

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

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

3817: .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3818: @*/
3819: PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3820: {
3821:   PetscFunctionBegin;
3826:   PetscCheckSameComm(mat, 1, b, 2);
3827:   PetscCheckSameComm(mat, 1, x, 3);
3828:   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3829:   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3830:   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3831:   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3832:   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3833:   MatCheckPreallocated(mat, 1);

3835:   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3836:   PetscUseTypeMethod(mat, forwardsolve, b, x);
3837:   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3838:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3839:   PetscFunctionReturn(PETSC_SUCCESS);
3840: }

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

3846:    Neighbor-wise Collective

3848:    Input Parameters:
3849: +  mat - the factored matrix
3850: -  b - the right-hand-side vector

3852:    Output Parameter:
3853: .  x - the result vector

3855:    Level: developer

3857:    Notes:
3858:    `MatSolve()` should be used for most applications, as it performs
3859:    a forward solve followed by a backward solve.

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

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

3870: .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3871: @*/
3872: PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3873: {
3874:   PetscFunctionBegin;
3879:   PetscCheckSameComm(mat, 1, b, 2);
3880:   PetscCheckSameComm(mat, 1, x, 3);
3881:   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3882:   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3883:   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3884:   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3885:   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3886:   MatCheckPreallocated(mat, 1);

3888:   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3889:   PetscUseTypeMethod(mat, backwardsolve, b, x);
3890:   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3891:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3892:   PetscFunctionReturn(PETSC_SUCCESS);
3893: }

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

3898:    Neighbor-wise Collective

3900:    Input Parameters:
3901: +  mat - the factored matrix
3902: .  b - the right-hand-side vector
3903: -  y - the vector to be added to

3905:    Output Parameter:
3906: .  x - the result vector

3908:    Level: developer

3910:    Note:
3911:    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3912:    call `MatSolveAdd`(A,x,y,x).

3914: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3915: @*/
3916: PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3917: {
3918:   PetscScalar one = 1.0;
3919:   Vec         tmp;

3921:   PetscFunctionBegin;
3927:   PetscCheckSameComm(mat, 1, b, 2);
3928:   PetscCheckSameComm(mat, 1, y, 3);
3929:   PetscCheckSameComm(mat, 1, x, 4);
3930:   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3931:   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3932:   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3933:   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
3934:   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3935:   PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n);
3936:   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3937:   MatCheckPreallocated(mat, 1);

3939:   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3940:   if (mat->factorerrortype) {
3941:     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3942:     PetscCall(VecSetInf(x));
3943:   } else if (mat->ops->solveadd) {
3944:     PetscUseTypeMethod(mat, solveadd, b, y, x);
3945:   } else {
3946:     /* do the solve then the add manually */
3947:     if (x != y) {
3948:       PetscCall(MatSolve(mat, b, x));
3949:       PetscCall(VecAXPY(x, one, y));
3950:     } else {
3951:       PetscCall(VecDuplicate(x, &tmp));
3952:       PetscCall(VecCopy(x, tmp));
3953:       PetscCall(MatSolve(mat, b, x));
3954:       PetscCall(VecAXPY(x, one, tmp));
3955:       PetscCall(VecDestroy(&tmp));
3956:     }
3957:   }
3958:   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3959:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3960:   PetscFunctionReturn(PETSC_SUCCESS);
3961: }

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

3966:    Neighbor-wise Collective

3968:    Input Parameters:
3969: +  mat - the factored matrix
3970: -  b - the right-hand-side vector

3972:    Output Parameter:
3973: .  x - the result vector

3975:    Level: developer

3977:    Notes:
3978:    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3979:    call `MatSolveTranspose`(A,x,x).

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

3985: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3986: @*/
3987: PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3988: {
3989:   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;

3991:   PetscFunctionBegin;
3996:   PetscCheckSameComm(mat, 1, b, 2);
3997:   PetscCheckSameComm(mat, 1, x, 3);
3998:   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3999:   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
4000:   PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N);
4001:   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4002:   MatCheckPreallocated(mat, 1);
4003:   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4004:   if (mat->factorerrortype) {
4005:     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4006:     PetscCall(VecSetInf(x));
4007:   } else {
4008:     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4009:     PetscCall((*f)(mat, b, x));
4010:   }
4011:   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4012:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4013:   PetscFunctionReturn(PETSC_SUCCESS);
4014: }

4016: /*@
4017:    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4018:                       factored matrix.

4020:    Neighbor-wise Collective

4022:    Input Parameters:
4023: +  mat - the factored matrix
4024: .  b - the right-hand-side vector
4025: -  y - the vector to be added to

4027:    Output Parameter:
4028: .  x - the result vector

4030:    Level: developer

4032:    Note:
4033:    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4034:    call `MatSolveTransposeAdd`(A,x,y,x).

4036: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4037: @*/
4038: PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4039: {
4040:   PetscScalar one = 1.0;
4041:   Vec         tmp;
4042:   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;

4044:   PetscFunctionBegin;
4050:   PetscCheckSameComm(mat, 1, b, 2);
4051:   PetscCheckSameComm(mat, 1, y, 3);
4052:   PetscCheckSameComm(mat, 1, x, 4);
4053:   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4054:   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
4055:   PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N);
4056:   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
4057:   PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n);
4058:   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4059:   MatCheckPreallocated(mat, 1);

4061:   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4062:   if (mat->factorerrortype) {
4063:     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4064:     PetscCall(VecSetInf(x));
4065:   } else if (f) {
4066:     PetscCall((*f)(mat, b, y, x));
4067:   } else {
4068:     /* do the solve then the add manually */
4069:     if (x != y) {
4070:       PetscCall(MatSolveTranspose(mat, b, x));
4071:       PetscCall(VecAXPY(x, one, y));
4072:     } else {
4073:       PetscCall(VecDuplicate(x, &tmp));
4074:       PetscCall(VecCopy(x, tmp));
4075:       PetscCall(MatSolveTranspose(mat, b, x));
4076:       PetscCall(VecAXPY(x, one, tmp));
4077:       PetscCall(VecDestroy(&tmp));
4078:     }
4079:   }
4080:   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4081:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4082:   PetscFunctionReturn(PETSC_SUCCESS);
4083: }

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

4088:    Neighbor-wise Collective

4090:    Input Parameters:
4091: +  mat - the matrix
4092: .  b - the right hand side
4093: .  omega - the relaxation factor
4094: .  flag - flag indicating the type of SOR (see below)
4095: .  shift -  diagonal shift
4096: .  its - the number of iterations
4097: -  lits - the number of local iterations

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

4102:    SOR Flags:
4103: +     `SOR_FORWARD_SWEEP` - forward SOR
4104: .     `SOR_BACKWARD_SWEEP` - backward SOR
4105: .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4106: .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4107: .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4108: .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4109: .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4110: .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4111:          upper/lower triangular part of matrix to
4112:          vector (with omega)
4113: -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess

4115:    Level: developer

4117:    Notes:
4118:    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4119:    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4120:    on each processor.

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

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

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

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

4133:    The flags are implemented as bitwise inclusive or operations.
4134:    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4135:    to specify a zero initial guess for SSOR.

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

4140: .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4141: @*/
4142: PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4143: {
4144:   PetscFunctionBegin;
4149:   PetscCheckSameComm(mat, 1, b, 2);
4150:   PetscCheckSameComm(mat, 1, x, 8);
4151:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4152:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4153:   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
4154:   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
4155:   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
4156:   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4157:   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4158:   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");

4160:   MatCheckPreallocated(mat, 1);
4161:   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4162:   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4163:   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4164:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4165:   PetscFunctionReturn(PETSC_SUCCESS);
4166: }

4168: /*
4169:       Default matrix copy routine.
4170: */
4171: PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4172: {
4173:   PetscInt           i, rstart = 0, rend = 0, nz;
4174:   const PetscInt    *cwork;
4175:   const PetscScalar *vwork;

4177:   PetscFunctionBegin;
4178:   if (B->assembled) PetscCall(MatZeroEntries(B));
4179:   if (str == SAME_NONZERO_PATTERN) {
4180:     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4181:     for (i = rstart; i < rend; i++) {
4182:       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4183:       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4184:       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4185:     }
4186:   } else {
4187:     PetscCall(MatAYPX(B, 0.0, A, str));
4188:   }
4189:   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4190:   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4191:   PetscFunctionReturn(PETSC_SUCCESS);
4192: }

4194: /*@
4195:    MatCopy - Copies a matrix to another matrix.

4197:    Collective

4199:    Input Parameters:
4200: +  A - the matrix
4201: -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`

4203:    Output Parameter:
4204: .  B - where the copy is put

4206:    Level: intermediate

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

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

4215: .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4216: @*/
4217: PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4218: {
4219:   PetscInt i;

4221:   PetscFunctionBegin;
4226:   PetscCheckSameComm(A, 1, B, 2);
4227:   MatCheckPreallocated(B, 2);
4228:   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4229:   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4230:   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")", A->rmap->N, B->rmap->N,
4231:              A->cmap->N, B->cmap->N);
4232:   MatCheckPreallocated(A, 1);
4233:   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);

4235:   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4236:   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4237:   else PetscCall(MatCopy_Basic(A, B, str));

4239:   B->stencil.dim = A->stencil.dim;
4240:   B->stencil.noc = A->stencil.noc;
4241:   for (i = 0; i <= A->stencil.dim; i++) {
4242:     B->stencil.dims[i]   = A->stencil.dims[i];
4243:     B->stencil.starts[i] = A->stencil.starts[i];
4244:   }

4246:   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4247:   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4248:   PetscFunctionReturn(PETSC_SUCCESS);
4249: }

4251: /*@C
4252:    MatConvert - Converts a matrix to another matrix, either of the same
4253:    or different type.

4255:    Collective

4257:    Input Parameters:
4258: +  mat - the matrix
4259: .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4260:    same type as the original matrix.
4261: -  reuse - denotes if the destination matrix is to be created or reused.
4262:    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
4263:    `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).

4265:    Output Parameter:
4266: .  M - pointer to place new matrix

4268:    Level: intermediate

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

4275:    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4276:    the MPI communicator of the generated matrix is always the same as the communicator
4277:    of the input matrix.

4279: .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4280: @*/
4281: PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4282: {
4283:   PetscBool  sametype, issame, flg;
4284:   PetscBool3 issymmetric, ishermitian;
4285:   char       convname[256], mtype[256];
4286:   Mat        B;

4288:   PetscFunctionBegin;
4292:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4293:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4294:   MatCheckPreallocated(mat, 1);

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

4299:   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4300:   PetscCall(PetscStrcmp(newtype, "same", &issame));
4301:   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4302:   PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");

4304:   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4305:     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4306:     PetscFunctionReturn(PETSC_SUCCESS);
4307:   }

4309:   /* Cache Mat options because some converters use MatHeaderReplace  */
4310:   issymmetric = mat->symmetric;
4311:   ishermitian = mat->hermitian;

4313:   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4314:     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4315:     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4316:   } else {
4317:     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4318:     const char *prefix[3]                                 = {"seq", "mpi", ""};
4319:     PetscInt    i;
4320:     /*
4321:        Order of precedence:
4322:        0) See if newtype is a superclass of the current matrix.
4323:        1) See if a specialized converter is known to the current matrix.
4324:        2) See if a specialized converter is known to the desired matrix class.
4325:        3) See if a good general converter is registered for the desired class
4326:           (as of 6/27/03 only MATMPIADJ falls into this category).
4327:        4) See if a good general converter is known for the current matrix.
4328:        5) Use a really basic converter.
4329:     */

4331:     /* 0) See if newtype is a superclass of the current matrix.
4332:           i.e mat is mpiaij and newtype is aij */
4333:     for (i = 0; i < 2; i++) {
4334:       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4335:       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4336:       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4337:       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4338:       if (flg) {
4339:         if (reuse == MAT_INPLACE_MATRIX) {
4340:           PetscCall(PetscInfo(mat, "Early return\n"));
4341:           PetscFunctionReturn(PETSC_SUCCESS);
4342:         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4343:           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4344:           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4345:           PetscFunctionReturn(PETSC_SUCCESS);
4346:         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4347:           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4348:           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4349:           PetscFunctionReturn(PETSC_SUCCESS);
4350:         }
4351:       }
4352:     }
4353:     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4354:     for (i = 0; i < 3; i++) {
4355:       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4356:       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4357:       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4358:       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4359:       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4360:       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4361:       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4362:       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4363:       if (conv) goto foundconv;
4364:     }

4366:     /* 2)  See if a specialized converter is known to the desired matrix class. */
4367:     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4368:     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4369:     PetscCall(MatSetType(B, newtype));
4370:     for (i = 0; i < 3; i++) {
4371:       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4372:       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4373:       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4374:       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4375:       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4376:       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4377:       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4378:       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4379:       if (conv) {
4380:         PetscCall(MatDestroy(&B));
4381:         goto foundconv;
4382:       }
4383:     }

4385:     /* 3) See if a good general converter is registered for the desired class */
4386:     conv = B->ops->convertfrom;
4387:     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4388:     PetscCall(MatDestroy(&B));
4389:     if (conv) goto foundconv;

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

4396:     /* 5) Use a really basic converter. */
4397:     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4398:     conv = MatConvert_Basic;

4400:   foundconv:
4401:     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4402:     PetscCall((*conv)(mat, newtype, reuse, M));
4403:     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4404:       /* the block sizes must be same if the mappings are copied over */
4405:       (*M)->rmap->bs = mat->rmap->bs;
4406:       (*M)->cmap->bs = mat->cmap->bs;
4407:       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4408:       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4409:       (*M)->rmap->mapping = mat->rmap->mapping;
4410:       (*M)->cmap->mapping = mat->cmap->mapping;
4411:     }
4412:     (*M)->stencil.dim = mat->stencil.dim;
4413:     (*M)->stencil.noc = mat->stencil.noc;
4414:     for (i = 0; i <= mat->stencil.dim; i++) {
4415:       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4416:       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4417:     }
4418:     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4419:   }
4420:   PetscCall(PetscObjectStateIncrease((PetscObject)*M));

4422:   /* Copy Mat options */
4423:   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4424:   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4425:   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4426:   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4427:   PetscFunctionReturn(PETSC_SUCCESS);
4428: }

4430: /*@C
4431:    MatFactorGetSolverType - Returns name of the package providing the factorization routines

4433:    Not Collective

4435:    Input Parameter:
4436: .  mat - the matrix, must be a factored matrix

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

4441:    Level: intermediate

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

4446: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4447: @*/
4448: PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4449: {
4450:   PetscErrorCode (*conv)(Mat, MatSolverType *);

4452:   PetscFunctionBegin;
4456:   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4457:   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4458:   if (conv) PetscCall((*conv)(mat, type));
4459:   else *type = MATSOLVERPETSC;
4460:   PetscFunctionReturn(PETSC_SUCCESS);
4461: }

4463: typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4464: struct _MatSolverTypeForSpecifcType {
4465:   MatType mtype;
4466:   /* no entry for MAT_FACTOR_NONE */
4467:   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4468:   MatSolverTypeForSpecifcType next;
4469: };

4471: typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4472: struct _MatSolverTypeHolder {
4473:   char                       *name;
4474:   MatSolverTypeForSpecifcType handlers;
4475:   MatSolverTypeHolder         next;
4476: };

4478: static MatSolverTypeHolder MatSolverTypeHolders = NULL;

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

4483:    Input Parameters:
4484: +    package - name of the package, for example petsc or superlu
4485: .    mtype - the matrix type that works with this package
4486: .    ftype - the type of factorization supported by the package
4487: -    createfactor - routine that will create the factored matrix ready to be used

4489:     Level: developer

4491: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4492: @*/
4493: PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4494: {
4495:   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4496:   PetscBool                   flg;
4497:   MatSolverTypeForSpecifcType inext, iprev = NULL;

4499:   PetscFunctionBegin;
4500:   PetscCall(MatInitializePackage());
4501:   if (!next) {
4502:     PetscCall(PetscNew(&MatSolverTypeHolders));
4503:     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4504:     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4505:     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4506:     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4507:     PetscFunctionReturn(PETSC_SUCCESS);
4508:   }
4509:   while (next) {
4510:     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4511:     if (flg) {
4512:       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4513:       inext = next->handlers;
4514:       while (inext) {
4515:         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4516:         if (flg) {
4517:           inext->createfactor[(int)ftype - 1] = createfactor;
4518:           PetscFunctionReturn(PETSC_SUCCESS);
4519:         }
4520:         iprev = inext;
4521:         inext = inext->next;
4522:       }
4523:       PetscCall(PetscNew(&iprev->next));
4524:       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4525:       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4526:       PetscFunctionReturn(PETSC_SUCCESS);
4527:     }
4528:     prev = next;
4529:     next = next->next;
4530:   }
4531:   PetscCall(PetscNew(&prev->next));
4532:   PetscCall(PetscStrallocpy(package, &prev->next->name));
4533:   PetscCall(PetscNew(&prev->next->handlers));
4534:   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4535:   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4536:   PetscFunctionReturn(PETSC_SUCCESS);
4537: }

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

4542:    Input Parameters:
4543: +    type - name of the package, for example petsc or superlu
4544: .    ftype - the type of factorization supported by the type
4545: -    mtype - the matrix type that works with this type

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

4552:     Level: developer

4554: .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4555: @*/
4556: PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4557: {
4558:   MatSolverTypeHolder         next = MatSolverTypeHolders;
4559:   PetscBool                   flg;
4560:   MatSolverTypeForSpecifcType inext;

4562:   PetscFunctionBegin;
4563:   if (foundtype) *foundtype = PETSC_FALSE;
4564:   if (foundmtype) *foundmtype = PETSC_FALSE;
4565:   if (createfactor) *createfactor = NULL;

4567:   if (type) {
4568:     while (next) {
4569:       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4570:       if (flg) {
4571:         if (foundtype) *foundtype = PETSC_TRUE;
4572:         inext = next->handlers;
4573:         while (inext) {
4574:           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4575:           if (flg) {
4576:             if (foundmtype) *foundmtype = PETSC_TRUE;
4577:             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4578:             PetscFunctionReturn(PETSC_SUCCESS);
4579:           }
4580:           inext = inext->next;
4581:         }
4582:       }
4583:       next = next->next;
4584:     }
4585:   } else {
4586:     while (next) {
4587:       inext = next->handlers;
4588:       while (inext) {
4589:         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4590:         if (flg && inext->createfactor[(int)ftype - 1]) {
4591:           if (foundtype) *foundtype = PETSC_TRUE;
4592:           if (foundmtype) *foundmtype = PETSC_TRUE;
4593:           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4594:           PetscFunctionReturn(PETSC_SUCCESS);
4595:         }
4596:         inext = inext->next;
4597:       }
4598:       next = next->next;
4599:     }
4600:     /* try with base classes inext->mtype */
4601:     next = MatSolverTypeHolders;
4602:     while (next) {
4603:       inext = next->handlers;
4604:       while (inext) {
4605:         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4606:         if (flg && inext->createfactor[(int)ftype - 1]) {
4607:           if (foundtype) *foundtype = PETSC_TRUE;
4608:           if (foundmtype) *foundmtype = PETSC_TRUE;
4609:           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4610:           PetscFunctionReturn(PETSC_SUCCESS);
4611:         }
4612:         inext = inext->next;
4613:       }
4614:       next = next->next;
4615:     }
4616:   }
4617:   PetscFunctionReturn(PETSC_SUCCESS);
4618: }

4620: PetscErrorCode MatSolverTypeDestroy(void)
4621: {
4622:   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4623:   MatSolverTypeForSpecifcType inext, iprev;

4625:   PetscFunctionBegin;
4626:   while (next) {
4627:     PetscCall(PetscFree(next->name));
4628:     inext = next->handlers;
4629:     while (inext) {
4630:       PetscCall(PetscFree(inext->mtype));
4631:       iprev = inext;
4632:       inext = inext->next;
4633:       PetscCall(PetscFree(iprev));
4634:     }
4635:     prev = next;
4636:     next = next->next;
4637:     PetscCall(PetscFree(prev));
4638:   }
4639:   MatSolverTypeHolders = NULL;
4640:   PetscFunctionReturn(PETSC_SUCCESS);
4641: }

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

4646:    Logically Collective

4648:    Input Parameters:
4649: .  mat - the matrix

4651:    Output Parameters:
4652: .  flg - `PETSC_TRUE` if uses the ordering

4654:    Level: developer

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

4660: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4661: @*/
4662: PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4663: {
4664:   PetscFunctionBegin;
4665:   *flg = mat->canuseordering;
4666:   PetscFunctionReturn(PETSC_SUCCESS);
4667: }

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

4672:    Logically Collective

4674:    Input Parameters:
4675: .  mat - the matrix obtained with `MatGetFactor()`

4677:    Output Parameters:
4678: .  otype - the preferred type

4680:    Level: developer

4682: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4683: @*/
4684: PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4685: {
4686:   PetscFunctionBegin;
4687:   *otype = mat->preferredordering[ftype];
4688:   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4689:   PetscFunctionReturn(PETSC_SUCCESS);
4690: }

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

4695:    Collective

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

4702:    Output Parameters:
4703: .  f - the factor matrix used with MatXXFactorSymbolic() calls

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

4709:    Level: intermediate

4711:    Notes:
4712:      Users usually access the factorization solvers via `KSP`

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

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

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

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

4726: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4727:           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4728: @*/
4729: PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4730: {
4731:   PetscBool foundtype, foundmtype;
4732:   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);

4734:   PetscFunctionBegin;

4738:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4739:   MatCheckPreallocated(mat, 1);

4741:   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4742:   if (!foundtype) {
4743:     if (type) {
4744:       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],
4745:               ((PetscObject)mat)->type_name, type);
4746:     } else {
4747:       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);
4748:     }
4749:   }
4750:   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4751:   PetscCheck(conv, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support factorization type %s for matrix type %s", type, MatFactorTypes[ftype], ((PetscObject)mat)->type_name);

4753:   PetscCall((*conv)(mat, ftype, f));
4754:   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4755:   PetscFunctionReturn(PETSC_SUCCESS);
4756: }

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

4761:    Not Collective

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

4768:    Output Parameter:
4769: .    flg - PETSC_TRUE if the factorization is available

4771:    Level: intermediate

4773:    Notes:
4774:       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4775:      such as pastix, superlu, mumps etc.

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

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

4782: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4783:           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4784: @*/
4785: PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4786: {
4787:   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);

4789:   PetscFunctionBegin;

4794:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4795:   MatCheckPreallocated(mat, 1);

4797:   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4798:   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4799:   PetscFunctionReturn(PETSC_SUCCESS);
4800: }

4802: /*@
4803:    MatDuplicate - Duplicates a matrix including the non-zero structure.

4805:    Collective

4807:    Input Parameters:
4808: +  mat - the matrix
4809: -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4810:         See the manual page for `MatDuplicateOption()` for an explanation of these options.

4812:    Output Parameter:
4813: .  M - pointer to place new matrix

4815:    Level: intermediate

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

4820:     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.

4822:     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
4823:     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4824:     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.

4826: .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4827: @*/
4828: PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4829: {
4830:   Mat         B;
4831:   VecType     vtype;
4832:   PetscInt    i;
4833:   PetscObject dm;
4834:   void (*viewf)(void);

4836:   PetscFunctionBegin;
4840:   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4841:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4842:   MatCheckPreallocated(mat, 1);

4844:   *M = NULL;
4845:   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4846:   PetscUseTypeMethod(mat, duplicate, op, M);
4847:   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4848:   B = *M;

4850:   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4851:   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4852:   PetscCall(MatGetVecType(mat, &vtype));
4853:   PetscCall(MatSetVecType(B, vtype));

4855:   B->stencil.dim = mat->stencil.dim;
4856:   B->stencil.noc = mat->stencil.noc;
4857:   for (i = 0; i <= mat->stencil.dim; i++) {
4858:     B->stencil.dims[i]   = mat->stencil.dims[i];
4859:     B->stencil.starts[i] = mat->stencil.starts[i];
4860:   }

4862:   B->nooffproczerorows = mat->nooffproczerorows;
4863:   B->nooffprocentries  = mat->nooffprocentries;

4865:   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4866:   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4867:   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4868:   PetscFunctionReturn(PETSC_SUCCESS);
4869: }

4871: /*@
4872:    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`

4874:    Logically Collective

4876:    Input Parameters:
4877: +  mat - the matrix
4878: -  v - the vector for storing the diagonal

4880:    Output Parameter:
4881: .  v - the diagonal of the matrix

4883:    Level: intermediate

4885:    Note:
4886:    Currently only correct in parallel for square matrices.

4888: .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4889: @*/
4890: PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4891: {
4892:   PetscFunctionBegin;
4896:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4897:   MatCheckPreallocated(mat, 1);

4899:   PetscUseTypeMethod(mat, getdiagonal, v);
4900:   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4901:   PetscFunctionReturn(PETSC_SUCCESS);
4902: }

4904: /*@C
4905:    MatGetRowMin - Gets the minimum value (of the real part) of each
4906:         row of the matrix

4908:    Logically Collective

4910:    Input Parameter:
4911: .  mat - the matrix

4913:    Output Parameters:
4914: +  v - the vector for storing the maximums
4915: -  idx - the indices of the column found for each row (optional)

4917:    Level: intermediate

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

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

4925: .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4926:           `MatGetRowMax()`
4927: @*/
4928: PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4929: {
4930:   PetscFunctionBegin;
4934:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");

4936:   if (!mat->cmap->N) {
4937:     PetscCall(VecSet(v, PETSC_MAX_REAL));
4938:     if (idx) {
4939:       PetscInt i, m = mat->rmap->n;
4940:       for (i = 0; i < m; i++) idx[i] = -1;
4941:     }
4942:   } else {
4943:     MatCheckPreallocated(mat, 1);
4944:   }
4945:   PetscUseTypeMethod(mat, getrowmin, v, idx);
4946:   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4947:   PetscFunctionReturn(PETSC_SUCCESS);
4948: }

4950: /*@C
4951:    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4952:         row of the matrix

4954:    Logically Collective

4956:    Input Parameter:
4957: .  mat - the matrix

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

4963:    Level: intermediate

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

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

4971: .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4972: @*/
4973: PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4974: {
4975:   PetscFunctionBegin;
4979:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4980:   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");

4982:   if (!mat->cmap->N) {
4983:     PetscCall(VecSet(v, 0.0));
4984:     if (idx) {
4985:       PetscInt i, m = mat->rmap->n;
4986:       for (i = 0; i < m; i++) idx[i] = -1;
4987:     }
4988:   } else {
4989:     MatCheckPreallocated(mat, 1);
4990:     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4991:     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4992:   }
4993:   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4994:   PetscFunctionReturn(PETSC_SUCCESS);
4995: }

4997: /*@C
4998:    MatGetRowMax - Gets the maximum value (of the real part) of each
4999:         row of the matrix

5001:    Logically Collective

5003:    Input Parameter:
5004: .  mat - the matrix

5006:    Output Parameters:
5007: +  v - the vector for storing the maximums
5008: -  idx - the indices of the column found for each row (optional)

5010:    Level: intermediate

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

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

5018: .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5019: @*/
5020: PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5021: {
5022:   PetscFunctionBegin;
5026:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");

5028:   if (!mat->cmap->N) {
5029:     PetscCall(VecSet(v, PETSC_MIN_REAL));
5030:     if (idx) {
5031:       PetscInt i, m = mat->rmap->n;
5032:       for (i = 0; i < m; i++) idx[i] = -1;
5033:     }
5034:   } else {
5035:     MatCheckPreallocated(mat, 1);
5036:     PetscUseTypeMethod(mat, getrowmax, v, idx);
5037:   }
5038:   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5039:   PetscFunctionReturn(PETSC_SUCCESS);
5040: }

5042: /*@C
5043:    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5044:         row of the matrix

5046:    Logically Collective

5048:    Input Parameter:
5049: .  mat - the matrix

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

5055:    Level: intermediate

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

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

5063: .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5064: @*/
5065: PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5066: {
5067:   PetscFunctionBegin;
5071:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");

5073:   if (!mat->cmap->N) {
5074:     PetscCall(VecSet(v, 0.0));
5075:     if (idx) {
5076:       PetscInt i, m = mat->rmap->n;
5077:       for (i = 0; i < m; i++) idx[i] = -1;
5078:     }
5079:   } else {
5080:     MatCheckPreallocated(mat, 1);
5081:     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5082:     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5083:   }
5084:   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5085:   PetscFunctionReturn(PETSC_SUCCESS);
5086: }

5088: /*@
5089:    MatGetRowSum - Gets the sum of each row of the matrix

5091:    Logically or Neighborhood Collective

5093:    Input Parameters:
5094: .  mat - the matrix

5096:    Output Parameter:
5097: .  v - the vector for storing the sum of rows

5099:    Level: intermediate

5101:    Notes:
5102:     This code is slow since it is not currently specialized for different formats

5104: .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5105: @*/
5106: PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5107: {
5108:   Vec ones;

5110:   PetscFunctionBegin;
5114:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5115:   MatCheckPreallocated(mat, 1);
5116:   PetscCall(MatCreateVecs(mat, &ones, NULL));
5117:   PetscCall(VecSet(ones, 1.));
5118:   PetscCall(MatMult(mat, ones, v));
5119:   PetscCall(VecDestroy(&ones));
5120:   PetscFunctionReturn(PETSC_SUCCESS);
5121: }

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

5127:    Collective

5129:    Input Parameter:
5130: .  mat - the matrix to provide the transpose

5132:    Output Parameter:
5133: .  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

5135:    Level: advanced

5137:    Note:
5138:    Normally the use of `MatTranspose`(A, `MAT_REUSE_MATRIX`, &B) requires that `B` was obtained with a call to `MatTranspose`(A, `MAT_INITIAL_MATRIX`, &B). This
5139:    routine allows bypassing that call.

5141: .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5142: @*/
5143: PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5144: {
5145:   PetscContainer  rB = NULL;
5146:   MatParentState *rb = NULL;

5148:   PetscFunctionBegin;
5149:   PetscCall(PetscNew(&rb));
5150:   rb->id    = ((PetscObject)mat)->id;
5151:   rb->state = 0;
5152:   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5153:   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5154:   PetscCall(PetscContainerSetPointer(rB, rb));
5155:   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5156:   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5157:   PetscCall(PetscObjectDereference((PetscObject)rB));
5158:   PetscFunctionReturn(PETSC_SUCCESS);
5159: }

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

5164:    Collective

5166:    Input Parameters:
5167: +  mat - the matrix to transpose
5168: -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`

5170:    Output Parameter:
5171: .  B - the transpose

5173:    Level: intermediate

5175:    Notes:
5176:      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B

5178:      `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
5179:      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.

5181:      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.

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

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

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

5189: .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5190:           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5191: @*/
5192: PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5193: {
5194:   PetscContainer  rB = NULL;
5195:   MatParentState *rb = NULL;

5197:   PetscFunctionBegin;
5200:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5201:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5202:   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5203:   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5204:   MatCheckPreallocated(mat, 1);
5205:   if (reuse == MAT_REUSE_MATRIX) {
5206:     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5207:     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5208:     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5209:     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5210:     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5211:   }

5213:   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5214:   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5215:     PetscUseTypeMethod(mat, transpose, reuse, B);
5216:     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5217:   }
5218:   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));

5220:   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5221:   if (reuse != MAT_INPLACE_MATRIX) {
5222:     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5223:     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5224:     rb->state        = ((PetscObject)mat)->state;
5225:     rb->nonzerostate = mat->nonzerostate;
5226:   }
5227:   PetscFunctionReturn(PETSC_SUCCESS);
5228: }

5230: /*@
5231:    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.

5233:    Collective

5235:    Input Parameters:
5236: .  A - the matrix to transpose

5238:    Output Parameter:
5239: .  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
5240:       numerical portion.

5242:    Level: intermediate

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

5247: .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5248: @*/
5249: PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5250: {
5251:   PetscFunctionBegin;
5254:   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5255:   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5256:   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5257:   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5258:   PetscCall((*A->ops->transposesymbolic)(A, B));
5259:   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));

5261:   PetscCall(MatTransposeSetPrecursor(A, *B));
5262:   PetscFunctionReturn(PETSC_SUCCESS);
5263: }

5265: PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5266: {
5267:   PetscContainer  rB;
5268:   MatParentState *rb;

5270:   PetscFunctionBegin;
5273:   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5274:   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5275:   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5276:   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5277:   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5278:   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5279:   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5280:   PetscFunctionReturn(PETSC_SUCCESS);
5281: }

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

5287:    Collective

5289:    Input Parameters:
5290: +  A - the matrix to test
5291: -  B - the matrix to test against, this can equal the first parameter

5293:    Output Parameters:
5294: .  flg - the result

5296:    Level: intermediate

5298:    Notes:
5299:    Only available for `MATAIJ` matrices.

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

5304: .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5305: @*/
5306: PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5307: {
5308:   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);

5310:   PetscFunctionBegin;
5314:   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5315:   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5316:   *flg = PETSC_FALSE;
5317:   if (f && g) {
5318:     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5319:     PetscCall((*f)(A, B, tol, flg));
5320:   } else {
5321:     MatType mattype;

5323:     PetscCall(MatGetType(f ? B : A, &mattype));
5324:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5325:   }
5326:   PetscFunctionReturn(PETSC_SUCCESS);
5327: }

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

5332:    Collective

5334:    Input Parameters:
5335: +  mat - the matrix to transpose and complex conjugate
5336: -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`

5338:    Output Parameter:
5339: .  B - the Hermitian transpose

5341:    Level: intermediate

5343: .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5344: @*/
5345: PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5346: {
5347:   PetscFunctionBegin;
5348:   PetscCall(MatTranspose(mat, reuse, B));
5349: #if defined(PETSC_USE_COMPLEX)
5350:   PetscCall(MatConjugate(*B));
5351: #endif
5352:   PetscFunctionReturn(PETSC_SUCCESS);
5353: }

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

5358:    Collective

5360:    Input Parameters:
5361: +  A - the matrix to test
5362: -  B - the matrix to test against, this can equal the first parameter

5364:    Output Parameters:
5365: .  flg - the result

5367:    Level: intermediate

5369:    Notes:
5370:    Only available for `MATAIJ` matrices.

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

5376: .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5377: @*/
5378: PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5379: {
5380:   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);

5382:   PetscFunctionBegin;
5386:   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5387:   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5388:   if (f && g) {
5389:     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5390:     PetscCall((*f)(A, B, tol, flg));
5391:   }
5392:   PetscFunctionReturn(PETSC_SUCCESS);
5393: }

5395: /*@
5396:    MatPermute - Creates a new matrix with rows and columns permuted from the
5397:    original.

5399:    Collective

5401:    Input Parameters:
5402: +  mat - the matrix to permute
5403: .  row - row permutation, each processor supplies only the permutation for its rows
5404: -  col - column permutation, each processor supplies only the permutation for its columns

5406:    Output Parameters:
5407: .  B - the permuted matrix

5409:    Level: advanced

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

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

5420: .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5421: @*/
5422: PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5423: {
5424:   PetscFunctionBegin;
5430:   PetscCheckSameComm(mat, 1, row, 2);
5431:   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5432:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5433:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5434:   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5435:   MatCheckPreallocated(mat, 1);

5437:   if (mat->ops->permute) {
5438:     PetscUseTypeMethod(mat, permute, row, col, B);
5439:     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5440:   } else {
5441:     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5442:   }
5443:   PetscFunctionReturn(PETSC_SUCCESS);
5444: }

5446: /*@
5447:    MatEqual - Compares two matrices.

5449:    Collective

5451:    Input Parameters:
5452: +  A - the first matrix
5453: -  B - the second matrix

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

5458:    Level: intermediate

5460: .seealso: [](chapter_matrices), `Mat`
5461: @*/
5462: PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5463: {
5464:   PetscFunctionBegin;
5470:   PetscCheckSameComm(A, 1, B, 2);
5471:   MatCheckPreallocated(A, 1);
5472:   MatCheckPreallocated(B, 2);
5473:   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5474:   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5475:   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N,
5476:              B->cmap->N);
5477:   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5478:     PetscUseTypeMethod(A, equal, B, flg);
5479:   } else {
5480:     PetscCall(MatMultEqual(A, B, 10, flg));
5481:   }
5482:   PetscFunctionReturn(PETSC_SUCCESS);
5483: }

5485: /*@
5486:    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5487:    matrices that are stored as vectors.  Either of the two scaling
5488:    matrices can be `NULL`.

5490:    Collective

5492:    Input Parameters:
5493: +  mat - the matrix to be scaled
5494: .  l - the left scaling vector (or `NULL`)
5495: -  r - the right scaling vector (or `NULL`)

5497:    Level: intermediate

5499:    Note:
5500:    `MatDiagonalScale()` computes A = LAR, where
5501:    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5502:    The L scales the rows of the matrix, the R scales the columns of the matrix.

5504: .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5505: @*/
5506: PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5507: {
5508:   PetscFunctionBegin;
5511:   if (l) {
5513:     PetscCheckSameComm(mat, 1, l, 2);
5514:   }
5515:   if (r) {
5517:     PetscCheckSameComm(mat, 1, r, 3);
5518:   }
5519:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5520:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5521:   MatCheckPreallocated(mat, 1);
5522:   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);

5524:   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5525:   PetscUseTypeMethod(mat, diagonalscale, l, r);
5526:   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5527:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5528:   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5529:   PetscFunctionReturn(PETSC_SUCCESS);
5530: }

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

5535:     Logically Collective

5537:     Input Parameters:
5538: +   mat - the matrix to be scaled
5539: -   a  - the scaling value

5541:     Output Parameter:
5542: .   mat - the scaled matrix

5544:     Level: intermediate

5546: .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
5547: @*/
5548: PetscErrorCode MatScale(Mat mat, PetscScalar a)
5549: {
5550:   PetscFunctionBegin;
5553:   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5554:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5555:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5557:   MatCheckPreallocated(mat, 1);

5559:   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5560:   if (a != (PetscScalar)1.0) {
5561:     PetscUseTypeMethod(mat, scale, a);
5562:     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5563:   }
5564:   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5565:   PetscFunctionReturn(PETSC_SUCCESS);
5566: }

5568: /*@
5569:    MatNorm - Calculates various norms of a matrix.

5571:    Collective

5573:    Input Parameters:
5574: +  mat - the matrix
5575: -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`

5577:    Output Parameter:
5578: .  nrm - the resulting norm

5580:    Level: intermediate

5582: .seealso: [](chapter_matrices), `Mat`
5583: @*/
5584: PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5585: {
5586:   PetscFunctionBegin;

5591:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5592:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5593:   MatCheckPreallocated(mat, 1);

5595:   PetscUseTypeMethod(mat, norm, type, nrm);
5596:   PetscFunctionReturn(PETSC_SUCCESS);
5597: }

5599: /*
5600:      This variable is used to prevent counting of MatAssemblyBegin() that
5601:    are called from within a MatAssemblyEnd().
5602: */
5603: static PetscInt MatAssemblyEnd_InUse = 0;
5604: /*@
5605:    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5606:    be called after completing all calls to `MatSetValues()`.

5608:    Collective

5610:    Input Parameters:
5611: +  mat - the matrix
5612: -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`

5614:    Level: beginner

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

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

5624:    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5625:    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
5626:    a global collective operation requiring all processes that share the matrix.

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

5632: .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5633: @*/
5634: PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5635: {
5636:   PetscFunctionBegin;
5639:   MatCheckPreallocated(mat, 1);
5640:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5641:   if (mat->assembled) {
5642:     mat->was_assembled = PETSC_TRUE;
5643:     mat->assembled     = PETSC_FALSE;
5644:   }

5646:   if (!MatAssemblyEnd_InUse) {
5647:     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5648:     PetscTryTypeMethod(mat, assemblybegin, type);
5649:     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5650:   } else PetscTryTypeMethod(mat, assemblybegin, type);
5651:   PetscFunctionReturn(PETSC_SUCCESS);
5652: }

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

5658:    Not Collective

5660:    Input Parameter:
5661: .  mat - the matrix

5663:    Output Parameter:
5664: .  assembled - `PETSC_TRUE` or `PETSC_FALSE`

5666:    Level: advanced

5668: .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5669: @*/
5670: PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5671: {
5672:   PetscFunctionBegin;
5675:   *assembled = mat->assembled;
5676:   PetscFunctionReturn(PETSC_SUCCESS);
5677: }

5679: /*@
5680:    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5681:    be called after `MatAssemblyBegin()`.

5683:    Collective

5685:    Input Parameters:
5686: +  mat - the matrix
5687: -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`

5689:    Options Database Keys:
5690: +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5691: .  -mat_view ::ascii_info_detail - Prints more detailed info
5692: .  -mat_view - Prints matrix in ASCII format
5693: .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5694: .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5695: .  -display <name> - Sets display name (default is host)
5696: .  -draw_pause <sec> - Sets number of seconds to pause after display
5697: .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5698: .  -viewer_socket_machine <machine> - Machine to use for socket
5699: .  -viewer_socket_port <port> - Port number to use for socket
5700: -  -mat_view binary:filename[:append] - Save matrix to file in binary format

5702:    Level: beginner

5704: .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5705: @*/
5706: PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5707: {
5708:   static PetscInt inassm = 0;
5709:   PetscBool       flg    = PETSC_FALSE;

5711:   PetscFunctionBegin;

5715:   inassm++;
5716:   MatAssemblyEnd_InUse++;
5717:   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5718:     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5719:     PetscTryTypeMethod(mat, assemblyend, type);
5720:     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5721:   } else PetscTryTypeMethod(mat, assemblyend, type);

5723:   /* Flush assembly is not a true assembly */
5724:   if (type != MAT_FLUSH_ASSEMBLY) {
5725:     if (mat->num_ass) {
5726:       if (!mat->symmetry_eternal) {
5727:         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5728:         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5729:       }
5730:       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5731:       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5732:     }
5733:     mat->num_ass++;
5734:     mat->assembled        = PETSC_TRUE;
5735:     mat->ass_nonzerostate = mat->nonzerostate;
5736:   }

5738:   mat->insertmode = NOT_SET_VALUES;
5739:   MatAssemblyEnd_InUse--;
5740:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5741:   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5742:     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));

5744:     if (mat->checksymmetryonassembly) {
5745:       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5746:       if (flg) {
5747:         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5748:       } else {
5749:         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5750:       }
5751:     }
5752:     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5753:   }
5754:   inassm--;
5755:   PetscFunctionReturn(PETSC_SUCCESS);
5756: }

5758: /*@
5759:    MatSetOption - Sets a parameter option for a matrix. Some options
5760:    may be specific to certain storage formats.  Some options
5761:    determine how values will be inserted (or added). Sorted,
5762:    row-oriented input will generally assemble the fastest. The default
5763:    is row-oriented.

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

5767:    Input Parameters:
5768: +  mat - the matrix
5769: .  option - the option, one of those listed below (and possibly others),
5770: -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)

5772:   Options Describing Matrix Structure:
5773: +    `MAT_SPD` - symmetric positive definite
5774: .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5775: .    `MAT_HERMITIAN` - transpose is the complex conjugation
5776: .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5777: .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5778: .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5779: -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix

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

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

5788:    These options reflect the data you pass in with `MatSetValues()`; it has
5789:    nothing to do with how the data is stored internally in the matrix
5790:    data structure.

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

5806:    Level: intermediate

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

5811:    Some options are relevant only for particular matrix types and
5812:    are thus ignored by others.  Other options are not supported by
5813:    certain matrix types and will generate an error message if set.

5815:    If using Fortran to compute a matrix, one may need to
5816:    use the column-oriented option (or convert to the row-oriented
5817:    format).

5819:    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5820:    that would generate a new entry in the nonzero structure is instead
5821:    ignored.  Thus, if memory has not already been allocated for this particular
5822:    data, then the insertion is ignored. For dense matrices, in which
5823:    the entire array is allocated, no entries are ever ignored.
5824:    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction

5826:    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5827:    that would generate a new entry in the nonzero structure instead produces
5828:    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

5830:    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5831:    that would generate a new entry that has not been preallocated will
5832:    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5833:    only.) This is a useful flag when debugging matrix memory preallocation.
5834:    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction

5836:    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5837:    other processors should be dropped, rather than stashed.
5838:    This is useful if you know that the "owning" processor is also
5839:    always generating the correct matrix entries, so that PETSc need
5840:    not transfer duplicate entries generated on another processor.

5842:    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5843:    searches during matrix assembly. When this flag is set, the hash table
5844:    is created during the first matrix assembly. This hash table is
5845:    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5846:    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5847:    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5848:    supported by `MATMPIBAIJ` format only.

5850:    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5851:    are kept in the nonzero structure

5853:    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5854:    a zero location in the matrix

5856:    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types

5858:    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5859:         zero row routines and thus improves performance for very large process counts.

5861:    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5862:         part of the matrix (since they should match the upper triangular part).

5864:    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5865:                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5866:                      with finite difference schemes with non-periodic boundary conditions.

5868:    Developer Note:
5869:    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5870:    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5871:    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5872:    not changed.

5874: .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()`
5875: @*/
5876: PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5877: {
5878:   PetscFunctionBegin;
5880:   if (op > 0) {
5883:   }

5885:   PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op);

5887:   switch (op) {
5888:   case MAT_FORCE_DIAGONAL_ENTRIES:
5889:     mat->force_diagonals = flg;
5890:     PetscFunctionReturn(PETSC_SUCCESS);
5891:   case MAT_NO_OFF_PROC_ENTRIES:
5892:     mat->nooffprocentries = flg;
5893:     PetscFunctionReturn(PETSC_SUCCESS);
5894:   case MAT_SUBSET_OFF_PROC_ENTRIES:
5895:     mat->assembly_subset = flg;
5896:     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5897: #if !defined(PETSC_HAVE_MPIUNI)
5898:       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5899: #endif
5900:       mat->stash.first_assembly_done = PETSC_FALSE;
5901:     }
5902:     PetscFunctionReturn(PETSC_SUCCESS);
5903:   case MAT_NO_OFF_PROC_ZERO_ROWS:
5904:     mat->nooffproczerorows = flg;
5905:     PetscFunctionReturn(PETSC_SUCCESS);
5906:   case MAT_SPD:
5907:     if (flg) {
5908:       mat->spd                    = PETSC_BOOL3_TRUE;
5909:       mat->symmetric              = PETSC_BOOL3_TRUE;
5910:       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5911:     } else {
5912:       mat->spd = PETSC_BOOL3_FALSE;
5913:     }
5914:     break;
5915:   case MAT_SYMMETRIC:
5916:     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5917:     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5918: #if !defined(PETSC_USE_COMPLEX)
5919:     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5920: #endif
5921:     break;
5922:   case MAT_HERMITIAN:
5923:     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5924:     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5925: #if !defined(PETSC_USE_COMPLEX)
5926:     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5927: #endif
5928:     break;
5929:   case MAT_STRUCTURALLY_SYMMETRIC:
5930:     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5931:     break;
5932:   case MAT_SYMMETRY_ETERNAL:
5933:     PetscCheck(mat->symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SYMMETRY_ETERNAL without first setting MAT_SYMMETRIC to true or false");
5934:     mat->symmetry_eternal = flg;
5935:     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5936:     break;
5937:   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5938:     PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURAL_SYMMETRIC to true or false");
5939:     mat->structural_symmetry_eternal = flg;
5940:     break;
5941:   case MAT_SPD_ETERNAL:
5942:     PetscCheck(mat->spd != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SPD_ETERNAL without first setting MAT_SPD to true or false");
5943:     mat->spd_eternal = flg;
5944:     if (flg) {
5945:       mat->structural_symmetry_eternal = PETSC_TRUE;
5946:       mat->symmetry_eternal            = PETSC_TRUE;
5947:     }
5948:     break;
5949:   case MAT_STRUCTURE_ONLY:
5950:     mat->structure_only = flg;
5951:     break;
5952:   case MAT_SORTED_FULL:
5953:     mat->sortedfull = flg;
5954:     break;
5955:   default:
5956:     break;
5957:   }
5958:   PetscTryTypeMethod(mat, setoption, op, flg);
5959:   PetscFunctionReturn(PETSC_SUCCESS);
5960: }

5962: /*@
5963:    MatGetOption - Gets a parameter option that has been set for a matrix.

5965:    Logically Collective

5967:    Input Parameters:
5968: +  mat - the matrix
5969: -  option - the option, this only responds to certain options, check the code for which ones

5971:    Output Parameter:
5972: .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)

5974:    Level: intermediate

5976:     Notes:
5977:     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.

5979:     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5980:     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`

5982: .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5983:     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5984: @*/
5985: PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5986: {
5987:   PetscFunctionBegin;

5991:   PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op);
5992:   PetscCheck(((PetscObject)mat)->type_name, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_TYPENOTSET, "Cannot get options until type and size have been set, see MatSetType() and MatSetSizes()");

5994:   switch (op) {
5995:   case MAT_NO_OFF_PROC_ENTRIES:
5996:     *flg = mat->nooffprocentries;
5997:     break;
5998:   case MAT_NO_OFF_PROC_ZERO_ROWS:
5999:     *flg = mat->nooffproczerorows;
6000:     break;
6001:   case MAT_SYMMETRIC:
6002:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6003:     break;
6004:   case MAT_HERMITIAN:
6005:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6006:     break;
6007:   case MAT_STRUCTURALLY_SYMMETRIC:
6008:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6009:     break;
6010:   case MAT_SPD:
6011:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6012:     break;
6013:   case MAT_SYMMETRY_ETERNAL:
6014:     *flg = mat->symmetry_eternal;
6015:     break;
6016:   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6017:     *flg = mat->symmetry_eternal;
6018:     break;
6019:   default:
6020:     break;
6021:   }
6022:   PetscFunctionReturn(PETSC_SUCCESS);
6023: }

6025: /*@
6026:    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6027:    this routine retains the old nonzero structure.

6029:    Logically Collective

6031:    Input Parameters:
6032: .  mat - the matrix

6034:    Level: intermediate

6036:    Note:
6037:     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.
6038:    See the Performance chapter of the users manual for information on preallocating matrices.

6040: .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6041: @*/
6042: PetscErrorCode MatZeroEntries(Mat mat)
6043: {
6044:   PetscFunctionBegin;
6047:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6048:   PetscCheck(mat->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for matrices where you have set values but not yet assembled");
6049:   MatCheckPreallocated(mat, 1);

6051:   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6052:   PetscUseTypeMethod(mat, zeroentries);
6053:   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6054:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6055:   PetscFunctionReturn(PETSC_SUCCESS);
6056: }

6058: /*@
6059:    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6060:    of a set of rows and columns of a matrix.

6062:    Collective

6064:    Input Parameters:
6065: +  mat - the matrix
6066: .  numRows - the number of rows/columns to zero
6067: .  rows - the global row indices
6068: .  diag - value put in the diagonal of the eliminated rows
6069: .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6070: -  b - optional vector of the right hand side, that will be adjusted by provided solution entries

6072:    Level: intermediate

6074:    Notes:
6075:    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.

6077:    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6078:    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

6080:    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6081:    Krylov method to take advantage of the known solution on the zeroed rows.

6083:    For the parallel case, all processes that share the matrix (i.e.,
6084:    those in the communicator used for matrix creation) MUST call this
6085:    routine, regardless of whether any rows being zeroed are owned by
6086:    them.

6088:    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.

6090:    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6091:    list only rows local to itself).

6093:    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.

6095: .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6096:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6097: @*/
6098: PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6099: {
6100:   PetscFunctionBegin;
6104:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6105:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6106:   MatCheckPreallocated(mat, 1);

6108:   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6109:   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6110:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6111:   PetscFunctionReturn(PETSC_SUCCESS);
6112: }

6114: /*@
6115:    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6116:    of a set of rows and columns of a matrix.

6118:    Collective

6120:    Input Parameters:
6121: +  mat - the matrix
6122: .  is - the rows to zero
6123: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6124: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6125: -  b - optional vector of right hand side, that will be adjusted by provided solution

6127:    Level: intermediate

6129:    Note:
6130:    See `MatZeroRowsColumns()` for details on how this routine operates.

6132: .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6133:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6134: @*/
6135: PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6136: {
6137:   PetscInt        numRows;
6138:   const PetscInt *rows;

6140:   PetscFunctionBegin;
6145:   PetscCall(ISGetLocalSize(is, &numRows));
6146:   PetscCall(ISGetIndices(is, &rows));
6147:   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6148:   PetscCall(ISRestoreIndices(is, &rows));
6149:   PetscFunctionReturn(PETSC_SUCCESS);
6150: }

6152: /*@
6153:    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6154:    of a set of rows of a matrix.

6156:    Collective

6158:    Input Parameters:
6159: +  mat - the matrix
6160: .  numRows - the number of rows to zero
6161: .  rows - the global row indices
6162: .  diag - value put in the diagonal of the zeroed rows
6163: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6164: -  b - optional vector of right hand side, that will be adjusted by provided solution entries

6166:    Level: intermediate

6168:    Notes:
6169:    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.

6171:    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.

6173:    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6174:    Krylov method to take advantage of the known solution on the zeroed rows.

6176:    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)
6177:    from the matrix.

6179:    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6180:    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
6181:    formats this does not alter the nonzero structure.

6183:    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6184:    of the matrix is not changed the values are
6185:    merely zeroed.

6187:    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6188:    formats can optionally remove the main diagonal entry from the
6189:    nonzero structure as well, by passing 0.0 as the final argument).

6191:    For the parallel case, all processes that share the matrix (i.e.,
6192:    those in the communicator used for matrix creation) MUST call this
6193:    routine, regardless of whether any rows being zeroed are owned by
6194:    them.

6196:    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6197:    list only rows local to itself).

6199:    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6200:    owns that are to be zeroed. This saves a global synchronization in the implementation.

6202: .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6203:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6204: @*/
6205: PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6206: {
6207:   PetscFunctionBegin;
6211:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6212:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6213:   MatCheckPreallocated(mat, 1);

6215:   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6216:   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6217:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6218:   PetscFunctionReturn(PETSC_SUCCESS);
6219: }

6221: /*@
6222:    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6223:    of a set of rows of a matrix.

6225:    Collective

6227:    Input Parameters:
6228: +  mat - the matrix
6229: .  is - index set of rows to remove (if `NULL` then no row is removed)
6230: .  diag - value put in all diagonals of eliminated rows
6231: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6232: -  b - optional vector of right hand side, that will be adjusted by provided solution

6234:    Level: intermediate

6236:    Note:
6237:    See `MatZeroRows()` for details on how this routine operates.

6239: .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6240:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6241: @*/
6242: PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6243: {
6244:   PetscInt        numRows = 0;
6245:   const PetscInt *rows    = NULL;

6247:   PetscFunctionBegin;
6250:   if (is) {
6252:     PetscCall(ISGetLocalSize(is, &numRows));
6253:     PetscCall(ISGetIndices(is, &rows));
6254:   }
6255:   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6256:   if (is) PetscCall(ISRestoreIndices(is, &rows));
6257:   PetscFunctionReturn(PETSC_SUCCESS);
6258: }

6260: /*@
6261:    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6262:    of a set of rows of a matrix. These rows must be local to the process.

6264:    Collective

6266:    Input Parameters:
6267: +  mat - the matrix
6268: .  numRows - the number of rows to remove
6269: .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6270: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6271: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6272: -  b - optional vector of right hand side, that will be adjusted by provided solution

6274:    Level: intermediate

6276:    Notes:
6277:    See `MatZeroRows()` for details on how this routine operates.

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

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

6286:    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
6287:    a single value per point) you can skip filling those indices.

6289:    Fortran Note:
6290:    `idxm` and `idxn` should be declared as
6291: $     MatStencil idxm(4,m)
6292:    and the values inserted using
6293: .vb
6294:     idxm(MatStencil_i,1) = i
6295:     idxm(MatStencil_j,1) = j
6296:     idxm(MatStencil_k,1) = k
6297:     idxm(MatStencil_c,1) = c
6298:    etc
6299: .ve

6301: .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6302:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6303: @*/
6304: PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6305: {
6306:   PetscInt  dim    = mat->stencil.dim;
6307:   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6308:   PetscInt *dims   = mat->stencil.dims + 1;
6309:   PetscInt *starts = mat->stencil.starts;
6310:   PetscInt *dxm    = (PetscInt *)rows;
6311:   PetscInt *jdxm, i, j, tmp, numNewRows = 0;

6313:   PetscFunctionBegin;

6318:   PetscCall(PetscMalloc1(numRows, &jdxm));
6319:   for (i = 0; i < numRows; ++i) {
6320:     /* Skip unused dimensions (they are ordered k, j, i, c) */
6321:     for (j = 0; j < 3 - sdim; ++j) dxm++;
6322:     /* Local index in X dir */
6323:     tmp = *dxm++ - starts[0];
6324:     /* Loop over remaining dimensions */
6325:     for (j = 0; j < dim - 1; ++j) {
6326:       /* If nonlocal, set index to be negative */
6327:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6328:       /* Update local index */
6329:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6330:     }
6331:     /* Skip component slot if necessary */
6332:     if (mat->stencil.noc) dxm++;
6333:     /* Local row number */
6334:     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6335:   }
6336:   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6337:   PetscCall(PetscFree(jdxm));
6338:   PetscFunctionReturn(PETSC_SUCCESS);
6339: }

6341: /*@
6342:    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6343:    of a set of rows and columns of a matrix.

6345:    Collective

6347:    Input Parameters:
6348: +  mat - the matrix
6349: .  numRows - the number of rows/columns to remove
6350: .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6351: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6352: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6353: -  b - optional vector of right hand side, that will be adjusted by provided solution

6355:    Level: intermediate

6357:    Notes:
6358:    See `MatZeroRowsColumns()` for details on how this routine operates.

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

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

6367:    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
6368:    a single value per point) you can skip filling those indices.

6370:    Fortran Note:
6371:    `idxm` and `idxn` should be declared as
6372: $     MatStencil idxm(4,m)
6373:    and the values inserted using
6374: .vb
6375:     idxm(MatStencil_i,1) = i
6376:     idxm(MatStencil_j,1) = j
6377:     idxm(MatStencil_k,1) = k
6378:     idxm(MatStencil_c,1) = c
6379:     etc
6380: .ve

6382: .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6383:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6384: @*/
6385: PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6386: {
6387:   PetscInt  dim    = mat->stencil.dim;
6388:   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6389:   PetscInt *dims   = mat->stencil.dims + 1;
6390:   PetscInt *starts = mat->stencil.starts;
6391:   PetscInt *dxm    = (PetscInt *)rows;
6392:   PetscInt *jdxm, i, j, tmp, numNewRows = 0;

6394:   PetscFunctionBegin;

6399:   PetscCall(PetscMalloc1(numRows, &jdxm));
6400:   for (i = 0; i < numRows; ++i) {
6401:     /* Skip unused dimensions (they are ordered k, j, i, c) */
6402:     for (j = 0; j < 3 - sdim; ++j) dxm++;
6403:     /* Local index in X dir */
6404:     tmp = *dxm++ - starts[0];
6405:     /* Loop over remaining dimensions */
6406:     for (j = 0; j < dim - 1; ++j) {
6407:       /* If nonlocal, set index to be negative */
6408:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6409:       /* Update local index */
6410:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6411:     }
6412:     /* Skip component slot if necessary */
6413:     if (mat->stencil.noc) dxm++;
6414:     /* Local row number */
6415:     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6416:   }
6417:   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6418:   PetscCall(PetscFree(jdxm));
6419:   PetscFunctionReturn(PETSC_SUCCESS);
6420: }

6422: /*@C
6423:    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6424:    of a set of rows of a matrix; using local numbering of rows.

6426:    Collective

6428:    Input Parameters:
6429: +  mat - the matrix
6430: .  numRows - the number of rows to remove
6431: .  rows - the local row indices
6432: .  diag - value put in all diagonals of eliminated rows
6433: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6434: -  b - optional vector of right hand side, that will be adjusted by provided solution

6436:    Level: intermediate

6438:    Notes:
6439:    Before calling `MatZeroRowsLocal()`, the user must first set the
6440:    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.

6442:    See `MatZeroRows()` for details on how this routine operates.

6444: .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6445:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6446: @*/
6447: PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6448: {
6449:   PetscFunctionBegin;
6453:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6454:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6455:   MatCheckPreallocated(mat, 1);

6457:   if (mat->ops->zerorowslocal) {
6458:     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6459:   } else {
6460:     IS              is, newis;
6461:     const PetscInt *newRows;

6463:     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6464:     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6465:     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6466:     PetscCall(ISGetIndices(newis, &newRows));
6467:     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6468:     PetscCall(ISRestoreIndices(newis, &newRows));
6469:     PetscCall(ISDestroy(&newis));
6470:     PetscCall(ISDestroy(&is));
6471:   }
6472:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6473:   PetscFunctionReturn(PETSC_SUCCESS);
6474: }

6476: /*@
6477:    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6478:    of a set of rows of a matrix; using local numbering of rows.

6480:    Collective

6482:    Input Parameters:
6483: +  mat - the matrix
6484: .  is - index set of rows to remove
6485: .  diag - value put in all diagonals of eliminated rows
6486: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6487: -  b - optional vector of right hand side, that will be adjusted by provided solution

6489:    Level: intermediate

6491:    Notes:
6492:    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6493:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6495:    See `MatZeroRows()` for details on how this routine operates.

6497: .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6498:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6499: @*/
6500: PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6501: {
6502:   PetscInt        numRows;
6503:   const PetscInt *rows;

6505:   PetscFunctionBegin;
6509:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6510:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6511:   MatCheckPreallocated(mat, 1);

6513:   PetscCall(ISGetLocalSize(is, &numRows));
6514:   PetscCall(ISGetIndices(is, &rows));
6515:   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6516:   PetscCall(ISRestoreIndices(is, &rows));
6517:   PetscFunctionReturn(PETSC_SUCCESS);
6518: }

6520: /*@
6521:    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6522:    of a set of rows and columns of a matrix; using local numbering of rows.

6524:    Collective

6526:    Input Parameters:
6527: +  mat - the matrix
6528: .  numRows - the number of rows to remove
6529: .  rows - the global row indices
6530: .  diag - value put in all diagonals of eliminated rows
6531: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6532: -  b - optional vector of right hand side, that will be adjusted by provided solution

6534:    Level: intermediate

6536:    Notes:
6537:    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6538:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6540:    See `MatZeroRowsColumns()` for details on how this routine operates.

6542: .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6543:           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6544: @*/
6545: PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6546: {
6547:   IS              is, newis;
6548:   const PetscInt *newRows;

6550:   PetscFunctionBegin;
6554:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6555:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6556:   MatCheckPreallocated(mat, 1);

6558:   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6559:   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6560:   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6561:   PetscCall(ISGetIndices(newis, &newRows));
6562:   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6563:   PetscCall(ISRestoreIndices(newis, &newRows));
6564:   PetscCall(ISDestroy(&newis));
6565:   PetscCall(ISDestroy(&is));
6566:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6567:   PetscFunctionReturn(PETSC_SUCCESS);
6568: }

6570: /*@
6571:    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6572:    of a set of rows and columns of a matrix; using local numbering of rows.

6574:    Collective

6576:    Input Parameters:
6577: +  mat - the matrix
6578: .  is - index set of rows to remove
6579: .  diag - value put in all diagonals of eliminated rows
6580: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6581: -  b - optional vector of right hand side, that will be adjusted by provided solution

6583:    Level: intermediate

6585:    Notes:
6586:    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6587:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6589:    See `MatZeroRowsColumns()` for details on how this routine operates.

6591: .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6592:           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6593: @*/
6594: PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6595: {
6596:   PetscInt        numRows;
6597:   const PetscInt *rows;

6599:   PetscFunctionBegin;
6603:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6604:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6605:   MatCheckPreallocated(mat, 1);

6607:   PetscCall(ISGetLocalSize(is, &numRows));
6608:   PetscCall(ISGetIndices(is, &rows));
6609:   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6610:   PetscCall(ISRestoreIndices(is, &rows));
6611:   PetscFunctionReturn(PETSC_SUCCESS);
6612: }

6614: /*@C
6615:    MatGetSize - Returns the numbers of rows and columns in a matrix.

6617:    Not Collective

6619:    Input Parameter:
6620: .  mat - the matrix

6622:    Level: beginner

6624:    Output Parameters:
6625: +  m - the number of global rows
6626: -  n - the number of global columns

6628:    Note:
6629:    Both output parameters can be `NULL` on input.

6631: .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6632: @*/
6633: PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6634: {
6635:   PetscFunctionBegin;
6637:   if (m) *m = mat->rmap->N;
6638:   if (n) *n = mat->cmap->N;
6639:   PetscFunctionReturn(PETSC_SUCCESS);
6640: }

6642: /*@C
6643:    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6644:    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.

6646:    Not Collective

6648:    Input Parameter:
6649: .  mat - the matrix

6651:    Output Parameters:
6652: +  m - the number of local rows, use `NULL` to not obtain this value
6653: -  n - the number of local columns, use `NULL` to not obtain this value

6655:    Level: beginner

6657: .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6658: @*/
6659: PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6660: {
6661:   PetscFunctionBegin;
6665:   if (m) *m = mat->rmap->n;
6666:   if (n) *n = mat->cmap->n;
6667:   PetscFunctionReturn(PETSC_SUCCESS);
6668: }

6670: /*@C
6671:    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6672:    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.

6674:    Not Collective, unless matrix has not been allocated, then collective

6676:    Input Parameter:
6677: .  mat - the matrix

6679:    Output Parameters:
6680: +  m - the global index of the first local column, use `NULL` to not obtain this value
6681: -  n - one more than the global index of the last local column, use `NULL` to not obtain this value

6683:    Level: developer

6685: .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6686: @*/
6687: PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6688: {
6689:   PetscFunctionBegin;
6694:   MatCheckPreallocated(mat, 1);
6695:   if (m) *m = mat->cmap->rstart;
6696:   if (n) *n = mat->cmap->rend;
6697:   PetscFunctionReturn(PETSC_SUCCESS);
6698: }

6700: /*@C
6701:    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6702:    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
6703:    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts

6705:    Not Collective

6707:    Input Parameter:
6708: .  mat - the matrix

6710:    Output Parameters:
6711: +  m - the global index of the first local row, use `NULL` to not obtain this value
6712: -  n - one more than the global index of the last local row, use `NULL` to not obtain this value

6714:    Level: beginner

6716:    Note:
6717:   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6718:   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6719:   and then `MPI_Scan()` to calculate prefix sums of the local sizes.

6721: .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6722:           `PetscLayout`
6723: @*/
6724: PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6725: {
6726:   PetscFunctionBegin;
6731:   MatCheckPreallocated(mat, 1);
6732:   if (m) *m = mat->rmap->rstart;
6733:   if (n) *n = mat->rmap->rend;
6734:   PetscFunctionReturn(PETSC_SUCCESS);
6735: }

6737: /*@C
6738:    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6739:    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
6740:    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts

6742:    Not Collective, unless matrix has not been allocated

6744:    Input Parameters:
6745: .  mat - the matrix

6747:    Output Parameters:
6748: .  ranges - start of each processors portion plus one more than the total length at the end

6750:    Level: beginner

6752: .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6753: @*/
6754: PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6755: {
6756:   PetscFunctionBegin;
6759:   MatCheckPreallocated(mat, 1);
6760:   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6761:   PetscFunctionReturn(PETSC_SUCCESS);
6762: }

6764: /*@C
6765:    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6766:    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.

6768:    Not Collective, unless matrix has not been allocated

6770:    Input Parameters:
6771: .  mat - the matrix

6773:    Output Parameters:
6774: .  ranges - start of each processors portion plus one more then the total length at the end

6776:    Level: beginner

6778: .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6779: @*/
6780: PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6781: {
6782:   PetscFunctionBegin;
6785:   MatCheckPreallocated(mat, 1);
6786:   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6787:   PetscFunctionReturn(PETSC_SUCCESS);
6788: }

6790: /*@C
6791:    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6792:    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6793:    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.

6795:    Not Collective

6797:    Input Parameter:
6798: .  A - matrix

6800:    Output Parameters:
6801: +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6802: -  cols - columns in which this process owns elements, use `NULL` to not obtain this value

6804:    Level: intermediate

6806: .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6807: @*/
6808: PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6809: {
6810:   PetscErrorCode (*f)(Mat, IS *, IS *);

6812:   PetscFunctionBegin;
6813:   MatCheckPreallocated(A, 1);
6814:   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6815:   if (f) {
6816:     PetscCall((*f)(A, rows, cols));
6817:   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6818:     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6819:     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6820:   }
6821:   PetscFunctionReturn(PETSC_SUCCESS);
6822: }

6824: /*@C
6825:    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6826:    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6827:    to complete the factorization.

6829:    Collective

6831:    Input Parameters:
6832: +  fact - the factorized matrix obtained with `MatGetFactor()`
6833: .  mat - the matrix
6834: .  row - row permutation
6835: .  column - column permutation
6836: -  info - structure containing
6837: .vb
6838:       levels - number of levels of fill.
6839:       expected fill - as ratio of original fill.
6840:       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6841:                 missing diagonal entries)
6842: .ve

6844:    Output Parameters:
6845: .  fact - new matrix that has been symbolically factored

6847:    Level: developer

6849:    Notes:
6850:    See [Matrix Factorization](sec_matfactor) for additional information.

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

6856:    Uses the definition of level of fill as in Y. Saad, 2003

6858:    Developer Note:
6859:    The Fortran interface is not autogenerated as the
6860:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

6862:    References:
6863: .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003

6865: .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6866:           `MatGetOrdering()`, `MatFactorInfo`
6867: @*/
6868: PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6869: {
6870:   PetscFunctionBegin;
6877:   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6878:   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6879:   if (!fact->ops->ilufactorsymbolic) {
6880:     MatSolverType stype;
6881:     PetscCall(MatFactorGetSolverType(fact, &stype));
6882:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6883:   }
6884:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6885:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6886:   MatCheckPreallocated(mat, 2);

6888:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6889:   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6890:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6891:   PetscFunctionReturn(PETSC_SUCCESS);
6892: }

6894: /*@C
6895:    MatICCFactorSymbolic - Performs symbolic incomplete
6896:    Cholesky factorization for a symmetric matrix.  Use
6897:    `MatCholeskyFactorNumeric()` to complete the factorization.

6899:    Collective

6901:    Input Parameters:
6902: +  fact - the factorized matrix obtained with `MatGetFactor()`
6903: .  mat - the matrix to be factored
6904: .  perm - row and column permutation
6905: -  info - structure containing
6906: .vb
6907:       levels - number of levels of fill.
6908:       expected fill - as ratio of original fill.
6909: .ve

6911:    Output Parameter:
6912: .  fact - the factored matrix

6914:    Level: developer

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

6921:    This uses the definition of level of fill as in Y. Saad, 2003

6923:    Developer Note:
6924:    The Fortran interface is not autogenerated as the
6925:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

6927:    References:
6928: .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003

6930: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6931: @*/
6932: PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6933: {
6934:   PetscFunctionBegin;
6940:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6941:   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6942:   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6943:   if (!(fact)->ops->iccfactorsymbolic) {
6944:     MatSolverType stype;
6945:     PetscCall(MatFactorGetSolverType(fact, &stype));
6946:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6947:   }
6948:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6949:   MatCheckPreallocated(mat, 2);

6951:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6952:   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6953:   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6954:   PetscFunctionReturn(PETSC_SUCCESS);
6955: }

6957: /*@C
6958:    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6959:    points to an array of valid matrices, they may be reused to store the new
6960:    submatrices.

6962:    Collective

6964:    Input Parameters:
6965: +  mat - the matrix
6966: .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6967: .  irow, icol - index sets of rows and columns to extract
6968: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

6970:    Output Parameter:
6971: .  submat - the array of submatrices

6973:    Level: advanced

6975:    Notes:
6976:    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6977:    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6978:    to extract a parallel submatrix.

6980:    Some matrix types place restrictions on the row and column
6981:    indices, such as that they be sorted or that they be equal to each other.

6983:    The index sets may not have duplicate entries.

6985:    When extracting submatrices from a parallel matrix, each processor can
6986:    form a different submatrix by setting the rows and columns of its
6987:    individual index sets according to the local submatrix desired.

6989:    When finished using the submatrices, the user should destroy
6990:    them with `MatDestroySubMatrices()`.

6992:    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6993:    original matrix has not changed from that last call to `MatCreateSubMatrices()`.

6995:    This routine creates the matrices in submat; you should NOT create them before
6996:    calling it. It also allocates the array of matrix pointers submat.

6998:    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6999:    request one row/column in a block, they must request all rows/columns that are in
7000:    that block. For example, if the block size is 2 you cannot request just row 0 and
7001:    column 0.

7003:    Fortran Note:
7004:    The Fortran interface is slightly different from that given below; it
7005:    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.

7007: .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7008: @*/
7009: PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7010: {
7011:   PetscInt  i;
7012:   PetscBool eq;

7014:   PetscFunctionBegin;
7017:   if (n) {
7022:   }
7024:   if (n && scall == MAT_REUSE_MATRIX) {
7027:   }
7028:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7029:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7030:   MatCheckPreallocated(mat, 1);
7031:   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7032:   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7033:   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7034:   for (i = 0; i < n; i++) {
7035:     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7036:     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7037:     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7038: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7039:     if (mat->boundtocpu && mat->bindingpropagates) {
7040:       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7041:       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7042:     }
7043: #endif
7044:   }
7045:   PetscFunctionReturn(PETSC_SUCCESS);
7046: }

7048: /*@C
7049:    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).

7051:    Collective

7053:    Input Parameters:
7054: +  mat - the matrix
7055: .  n   - the number of submatrixes to be extracted
7056: .  irow, icol - index sets of rows and columns to extract
7057: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

7059:    Output Parameter:
7060: .  submat - the array of submatrices

7062:    Level: advanced

7064:    Note:
7065:    This is used by `PCGASM`

7067: .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7068: @*/
7069: PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7070: {
7071:   PetscInt  i;
7072:   PetscBool eq;

7074:   PetscFunctionBegin;
7077:   if (n) {
7082:   }
7084:   if (n && scall == MAT_REUSE_MATRIX) {
7087:   }
7088:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7089:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7090:   MatCheckPreallocated(mat, 1);

7092:   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7093:   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7094:   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7095:   for (i = 0; i < n; i++) {
7096:     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7097:     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7098:   }
7099:   PetscFunctionReturn(PETSC_SUCCESS);
7100: }

7102: /*@C
7103:    MatDestroyMatrices - Destroys an array of matrices.

7105:    Collective

7107:    Input Parameters:
7108: +  n - the number of local matrices
7109: -  mat - the matrices (this is a pointer to the array of matrices)

7111:    Level: advanced

7113:     Note:
7114:     Frees not only the matrices, but also the array that contains the matrices

7116:     Fortran Note:
7117:     This does not free the array.

7119: .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7120: @*/
7121: PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7122: {
7123:   PetscInt i;

7125:   PetscFunctionBegin;
7126:   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7127:   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);

7130:   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));

7132:   /* memory is allocated even if n = 0 */
7133:   PetscCall(PetscFree(*mat));
7134:   PetscFunctionReturn(PETSC_SUCCESS);
7135: }

7137: /*@C
7138:    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.

7140:    Collective

7142:    Input Parameters:
7143: +  n - the number of local matrices
7144: -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7145:                        sequence of `MatCreateSubMatrices()`)

7147:    Level: advanced

7149:     Note:
7150:     Frees not only the matrices, but also the array that contains the matrices

7152:     Fortran Note:
7153:     This does not free the array.

7155: .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7156: @*/
7157: PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7158: {
7159:   Mat mat0;

7161:   PetscFunctionBegin;
7162:   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7163:   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7164:   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);

7167:   mat0 = (*mat)[0];
7168:   if (mat0 && mat0->ops->destroysubmatrices) {
7169:     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
7170:   } else {
7171:     PetscCall(MatDestroyMatrices(n, mat));
7172:   }
7173:   PetscFunctionReturn(PETSC_SUCCESS);
7174: }

7176: /*@C
7177:    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process

7179:    Collective

7181:    Input Parameters:
7182: .  mat - the matrix

7184:    Output Parameter:
7185: .  matstruct - the sequential matrix with the nonzero structure of mat

7187:   Level: developer

7189: .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7190: @*/
7191: PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7192: {
7193:   PetscFunctionBegin;

7198:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7199:   MatCheckPreallocated(mat, 1);

7201:   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7202:   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7203:   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7204:   PetscFunctionReturn(PETSC_SUCCESS);
7205: }

7207: /*@C
7208:    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.

7210:    Collective

7212:    Input Parameters:
7213: .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7214:                        sequence of `MatGetSequentialNonzeroStructure()`)

7216:    Level: advanced

7218:     Note:
7219:     Frees not only the matrices, but also the array that contains the matrices

7221: .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7222: @*/
7223: PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7224: {
7225:   PetscFunctionBegin;
7227:   PetscCall(MatDestroy(mat));
7228:   PetscFunctionReturn(PETSC_SUCCESS);
7229: }

7231: /*@
7232:    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7233:    replaces the index sets by larger ones that represent submatrices with
7234:    additional overlap.

7236:    Collective

7238:    Input Parameters:
7239: +  mat - the matrix
7240: .  n   - the number of index sets
7241: .  is  - the array of index sets (these index sets will changed during the call)
7242: -  ov  - the additional overlap requested

7244:    Options Database Key:
7245: .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)

7247:    Level: developer

7249:    Note:
7250:    The computed overlap preserves the matrix block sizes when the blocks are square.
7251:    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7252:    that block are included in the overlap regardless of whether each specific column would increase the overlap.

7254: .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7255: @*/
7256: PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7257: {
7258:   PetscInt i, bs, cbs;

7260:   PetscFunctionBegin;
7264:   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7265:   if (n) {
7268:   }
7269:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7270:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7271:   MatCheckPreallocated(mat, 1);

7273:   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7274:   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7275:   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7276:   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7277:   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7278:   if (bs == cbs) {
7279:     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7280:   }
7281:   PetscFunctionReturn(PETSC_SUCCESS);
7282: }

7284: PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);

7286: /*@
7287:    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7288:    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7289:    additional overlap.

7291:    Collective

7293:    Input Parameters:
7294: +  mat - the matrix
7295: .  n   - the number of index sets
7296: .  is  - the array of index sets (these index sets will changed during the call)
7297: -  ov  - the additional overlap requested

7299: `   Options Database Key:
7300: .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)

7302:    Level: developer

7304: .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7305: @*/
7306: PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7307: {
7308:   PetscInt i;

7310:   PetscFunctionBegin;
7313:   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7314:   if (n) {
7317:   }
7318:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7319:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7320:   MatCheckPreallocated(mat, 1);
7321:   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7322:   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7323:   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7324:   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7325:   PetscFunctionReturn(PETSC_SUCCESS);
7326: }

7328: /*@
7329:    MatGetBlockSize - Returns the matrix block size.

7331:    Not Collective

7333:    Input Parameter:
7334: .  mat - the matrix

7336:    Output Parameter:
7337: .  bs - block size

7339:    Level: intermediate

7341:    Notes:
7342:     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.

7344:    If the block size has not been set yet this routine returns 1.

7346: .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7347: @*/
7348: PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7349: {
7350:   PetscFunctionBegin;
7353:   *bs = PetscAbs(mat->rmap->bs);
7354:   PetscFunctionReturn(PETSC_SUCCESS);
7355: }

7357: /*@
7358:    MatGetBlockSizes - Returns the matrix block row and column sizes.

7360:    Not Collective

7362:    Input Parameter:
7363: .  mat - the matrix

7365:    Output Parameters:
7366: +  rbs - row block size
7367: -  cbs - column block size

7369:    Level: intermediate

7371:    Notes:
7372:     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7373:     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.

7375:    If a block size has not been set yet this routine returns 1.

7377: .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7378: @*/
7379: PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7380: {
7381:   PetscFunctionBegin;
7385:   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7386:   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7387:   PetscFunctionReturn(PETSC_SUCCESS);
7388: }

7390: /*@
7391:    MatSetBlockSize - Sets the matrix block size.

7393:    Logically Collective

7395:    Input Parameters:
7396: +  mat - the matrix
7397: -  bs - block size

7399:    Level: intermediate

7401:    Notes:
7402:     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7403:     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.

7405:     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7406:     is compatible with the matrix local sizes.

7408: .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7409: @*/
7410: PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7411: {
7412:   PetscFunctionBegin;
7415:   PetscCall(MatSetBlockSizes(mat, bs, bs));
7416:   PetscFunctionReturn(PETSC_SUCCESS);
7417: }

7419: typedef struct {
7420:   PetscInt         n;
7421:   IS              *is;
7422:   Mat             *mat;
7423:   PetscObjectState nonzerostate;
7424:   Mat              C;
7425: } EnvelopeData;

7427: static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7428: {
7429:   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7430:   PetscCall(PetscFree(edata->is));
7431:   PetscCall(PetscFree(edata));
7432:   return PETSC_SUCCESS;
7433: }

7435: /*
7436:    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7437:          the sizes of these blocks in the matrix. An individual block may lie over several processes.

7439:    Collective

7441:    Input Parameter:
7442: .  mat - the matrix

7444:    Notes:
7445:      There can be zeros within the blocks

7447:      The blocks can overlap between processes, including laying on more than two processes

7449: .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7450: */
7451: static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7452: {
7453:   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7454:   PetscInt          *diag, *odiag, sc;
7455:   VecScatter         scatter;
7456:   PetscScalar       *seqv;
7457:   const PetscScalar *parv;
7458:   const PetscInt    *ia, *ja;
7459:   PetscBool          set, flag, done;
7460:   Mat                AA = mat, A;
7461:   MPI_Comm           comm;
7462:   PetscMPIInt        rank, size, tag;
7463:   MPI_Status         status;
7464:   PetscContainer     container;
7465:   EnvelopeData      *edata;
7466:   Vec                seq, par;
7467:   IS                 isglobal;

7469:   PetscFunctionBegin;
7471:   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7472:   if (!set || !flag) {
7473:     /* TOO: only needs nonzero structure of transpose */
7474:     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7475:     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7476:   }
7477:   PetscCall(MatAIJGetLocalMat(AA, &A));
7478:   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7479:   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");

7481:   PetscCall(MatGetLocalSize(mat, &n, NULL));
7482:   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7483:   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7484:   PetscCallMPI(MPI_Comm_size(comm, &size));
7485:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

7487:   PetscCall(PetscMalloc2(n, &sizes, n, &starts));

7489:   if (rank > 0) {
7490:     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7491:     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7492:   }
7493:   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7494:   for (i = 0; i < n; i++) {
7495:     env = PetscMax(env, ja[ia[i + 1] - 1]);
7496:     II  = rstart + i;
7497:     if (env == II) {
7498:       starts[lblocks]  = tbs;
7499:       sizes[lblocks++] = 1 + II - tbs;
7500:       tbs              = 1 + II;
7501:     }
7502:   }
7503:   if (rank < size - 1) {
7504:     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7505:     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7506:   }

7508:   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7509:   if (!set || !flag) PetscCall(MatDestroy(&AA));
7510:   PetscCall(MatDestroy(&A));

7512:   PetscCall(PetscNew(&edata));
7513:   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7514:   edata->n = lblocks;
7515:   /* create IS needed for extracting blocks from the original matrix */
7516:   PetscCall(PetscMalloc1(lblocks, &edata->is));
7517:   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));

7519:   /* Create the resulting inverse matrix structure with preallocation information */
7520:   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7521:   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7522:   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7523:   PetscCall(MatSetType(edata->C, MATAIJ));

7525:   /* Communicate the start and end of each row, from each block to the correct rank */
7526:   /* TODO: Use PetscSF instead of VecScatter */
7527:   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7528:   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7529:   PetscCall(VecGetArrayWrite(seq, &seqv));
7530:   for (PetscInt i = 0; i < lblocks; i++) {
7531:     for (PetscInt j = 0; j < sizes[i]; j++) {
7532:       seqv[cnt]     = starts[i];
7533:       seqv[cnt + 1] = starts[i] + sizes[i];
7534:       cnt += 2;
7535:     }
7536:   }
7537:   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7538:   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7539:   sc -= cnt;
7540:   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7541:   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7542:   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7543:   PetscCall(ISDestroy(&isglobal));
7544:   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7545:   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7546:   PetscCall(VecScatterDestroy(&scatter));
7547:   PetscCall(VecDestroy(&seq));
7548:   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7549:   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7550:   PetscCall(VecGetArrayRead(par, &parv));
7551:   cnt = 0;
7552:   PetscCall(MatGetSize(mat, NULL, &n));
7553:   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7554:     PetscInt start, end, d = 0, od = 0;

7556:     start = (PetscInt)PetscRealPart(parv[cnt]);
7557:     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7558:     cnt += 2;

7560:     if (start < cstart) {
7561:       od += cstart - start + n - cend;
7562:       d += cend - cstart;
7563:     } else if (start < cend) {
7564:       od += n - cend;
7565:       d += cend - start;
7566:     } else od += n - start;
7567:     if (end <= cstart) {
7568:       od -= cstart - end + n - cend;
7569:       d -= cend - cstart;
7570:     } else if (end < cend) {
7571:       od -= n - cend;
7572:       d -= cend - end;
7573:     } else od -= n - end;

7575:     odiag[i] = od;
7576:     diag[i]  = d;
7577:   }
7578:   PetscCall(VecRestoreArrayRead(par, &parv));
7579:   PetscCall(VecDestroy(&par));
7580:   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7581:   PetscCall(PetscFree2(diag, odiag));
7582:   PetscCall(PetscFree2(sizes, starts));

7584:   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7585:   PetscCall(PetscContainerSetPointer(container, edata));
7586:   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7587:   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7588:   PetscCall(PetscObjectDereference((PetscObject)container));
7589:   PetscFunctionReturn(PETSC_SUCCESS);
7590: }

7592: /*@
7593:   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A

7595:   Collective

7597:   Input Parameters:
7598: . A - the matrix

7600:   Output Parameters:
7601: . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.

7603:   Level: advanced

7605:   Note:
7606:      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.

7608: .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7609: @*/
7610: PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7611: {
7612:   PetscContainer   container;
7613:   EnvelopeData    *edata;
7614:   PetscObjectState nonzerostate;

7616:   PetscFunctionBegin;
7617:   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7618:   if (!container) {
7619:     PetscCall(MatComputeVariableBlockEnvelope(A));
7620:     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7621:   }
7622:   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7623:   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7624:   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7625:   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");

7627:   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7628:   *C = edata->C;

7630:   for (PetscInt i = 0; i < edata->n; i++) {
7631:     Mat          D;
7632:     PetscScalar *dvalues;

7634:     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7635:     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7636:     PetscCall(MatSeqDenseInvert(D));
7637:     PetscCall(MatDenseGetArray(D, &dvalues));
7638:     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7639:     PetscCall(MatDestroy(&D));
7640:   }
7641:   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7642:   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7643:   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7644:   PetscFunctionReturn(PETSC_SUCCESS);
7645: }

7647: /*@
7648:    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size

7650:    Logically Collective

7652:    Input Parameters:
7653: +  mat - the matrix
7654: .  nblocks - the number of blocks on this process, each block can only exist on a single process
7655: -  bsizes - the block sizes

7657:    Level: intermediate

7659:    Notes:
7660:     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices

7662:     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.

7664: .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7665:           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7666: @*/
7667: PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7668: {
7669:   PetscInt i, ncnt = 0, nlocal;

7671:   PetscFunctionBegin;
7673:   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7674:   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7675:   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7676:   PetscCheck(ncnt == nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local block sizes %" PetscInt_FMT " does not equal local size of matrix %" PetscInt_FMT, ncnt, nlocal);
7677:   PetscCall(PetscFree(mat->bsizes));
7678:   mat->nblocks = nblocks;
7679:   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7680:   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7681:   PetscFunctionReturn(PETSC_SUCCESS);
7682: }

7684: /*@C
7685:    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size

7687:    Logically Collective; No Fortran Support

7689:    Input Parameter:
7690: .  mat - the matrix

7692:    Output Parameters:
7693: +  nblocks - the number of blocks on this process
7694: -  bsizes - the block sizes

7696:    Level: intermediate

7698: .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7699: @*/
7700: PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7701: {
7702:   PetscFunctionBegin;
7704:   *nblocks = mat->nblocks;
7705:   *bsizes  = mat->bsizes;
7706:   PetscFunctionReturn(PETSC_SUCCESS);
7707: }

7709: /*@
7710:    MatSetBlockSizes - Sets the matrix block row and column sizes.

7712:    Logically Collective

7714:    Input Parameters:
7715: +  mat - the matrix
7716: .  rbs - row block size
7717: -  cbs - column block size

7719:    Level: intermediate

7721:    Notes:
7722:     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7723:     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7724:     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.

7726:     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7727:     are compatible with the matrix local sizes.

7729:     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.

7731: .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7732: @*/
7733: PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7734: {
7735:   PetscFunctionBegin;
7739:   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7740:   if (mat->rmap->refcnt) {
7741:     ISLocalToGlobalMapping l2g  = NULL;
7742:     PetscLayout            nmap = NULL;

7744:     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7745:     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7746:     PetscCall(PetscLayoutDestroy(&mat->rmap));
7747:     mat->rmap          = nmap;
7748:     mat->rmap->mapping = l2g;
7749:   }
7750:   if (mat->cmap->refcnt) {
7751:     ISLocalToGlobalMapping l2g  = NULL;
7752:     PetscLayout            nmap = NULL;

7754:     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7755:     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7756:     PetscCall(PetscLayoutDestroy(&mat->cmap));
7757:     mat->cmap          = nmap;
7758:     mat->cmap->mapping = l2g;
7759:   }
7760:   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7761:   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7762:   PetscFunctionReturn(PETSC_SUCCESS);
7763: }

7765: /*@
7766:    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices

7768:    Logically Collective

7770:    Input Parameters:
7771: +  mat - the matrix
7772: .  fromRow - matrix from which to copy row block size
7773: -  fromCol - matrix from which to copy column block size (can be same as fromRow)

7775:    Level: developer

7777: .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7778: @*/
7779: PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7780: {
7781:   PetscFunctionBegin;
7785:   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7786:   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7787:   PetscFunctionReturn(PETSC_SUCCESS);
7788: }

7790: /*@
7791:    MatResidual - Default routine to calculate the residual r = b - Ax

7793:    Collective

7795:    Input Parameters:
7796: +  mat - the matrix
7797: .  b   - the right-hand-side
7798: -  x   - the approximate solution

7800:    Output Parameter:
7801: .  r - location to store the residual

7803:    Level: developer

7805: .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7806: @*/
7807: PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7808: {
7809:   PetscFunctionBegin;
7815:   MatCheckPreallocated(mat, 1);
7816:   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7817:   if (!mat->ops->residual) {
7818:     PetscCall(MatMult(mat, x, r));
7819:     PetscCall(VecAYPX(r, -1.0, b));
7820:   } else {
7821:     PetscUseTypeMethod(mat, residual, b, x, r);
7822:   }
7823:   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7824:   PetscFunctionReturn(PETSC_SUCCESS);
7825: }

7827: /*MC
7828:     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix

7830:     Synopsis:
7831:     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)

7833:     Not Collective

7835:     Input Parameters:
7836: +   A - the matrix
7837: .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7838: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7839: -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7840:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7841:                  always used.

7843:     Output Parameters:
7844: +   n - number of local rows in the (possibly compressed) matrix
7845: .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7846: .   ja - the column indices
7847: -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7848:            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set

7850:     Level: developer

7852:     Note:
7853:     Use  `MatRestoreRowIJF90()` when you no longer need access to the data

7855: .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7856: M*/

7858: /*MC
7859:     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`

7861:     Synopsis:
7862:     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)

7864:     Not Collective

7866:     Input Parameters:
7867: +   A - the  matrix
7868: .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7869: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7870:     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7871:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7872:                  always used.
7873: .   n - number of local rows in the (possibly compressed) matrix
7874: .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7875: .   ja - the column indices
7876: -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7877:            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set

7879:     Level: developer

7881: .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7882: M*/

7884: /*@C
7885:     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix

7887:    Collective

7889:     Input Parameters:
7890: +   mat - the matrix
7891: .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7892: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7893: -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7894:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7895:                  always used.

7897:     Output Parameters:
7898: +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7899: .   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
7900: .   ja - the column indices, use `NULL` if not needed
7901: -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7902:            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set

7904:     Level: developer

7906:     Notes:
7907:     You CANNOT change any of the ia[] or ja[] values.

7909:     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.

7911:     Fortran Notes:
7912:     Use
7913: .vb
7914:     PetscInt, pointer :: ia(:),ja(:)
7915:     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7916:     ! Access the ith and jth entries via ia(i) and ja(j)
7917: .ve
7918:    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`

7920: .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7921: @*/
7922: PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7923: {
7924:   PetscFunctionBegin;
7931:   MatCheckPreallocated(mat, 1);
7932:   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7933:   else {
7934:     if (done) *done = PETSC_TRUE;
7935:     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7936:     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7937:     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7938:   }
7939:   PetscFunctionReturn(PETSC_SUCCESS);
7940: }

7942: /*@C
7943:     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.

7945:     Collective

7947:     Input Parameters:
7948: +   mat - the matrix
7949: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7950: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7951:                 symmetrized
7952: .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7953:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7954:                  always used.
7955: .   n - number of columns in the (possibly compressed) matrix
7956: .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7957: -   ja - the row indices

7959:     Output Parameters:
7960: .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned

7962:     Level: developer

7964: .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7965: @*/
7966: PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7967: {
7968:   PetscFunctionBegin;
7975:   MatCheckPreallocated(mat, 1);
7976:   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7977:   else {
7978:     *done = PETSC_TRUE;
7979:     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7980:   }
7981:   PetscFunctionReturn(PETSC_SUCCESS);
7982: }

7984: /*@C
7985:     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.

7987:     Collective

7989:     Input Parameters:
7990: +   mat - the matrix
7991: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7992: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7993: .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7994:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7995:                  always used.
7996: .   n - size of (possibly compressed) matrix
7997: .   ia - the row pointers
7998: -   ja - the column indices

8000:     Output Parameters:
8001: .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned

8003:     Level: developer

8005:     Note:
8006:     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8007:     us of the array after it has been restored. If you pass `NULL`, it will
8008:     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.

8010:     Fortran Note:
8011:    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8012: .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8013: @*/
8014: PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8015: {
8016:   PetscFunctionBegin;
8022:   MatCheckPreallocated(mat, 1);

8024:   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8025:   else {
8026:     if (done) *done = PETSC_TRUE;
8027:     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8028:     if (n) *n = 0;
8029:     if (ia) *ia = NULL;
8030:     if (ja) *ja = NULL;
8031:   }
8032:   PetscFunctionReturn(PETSC_SUCCESS);
8033: }

8035: /*@C
8036:     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.

8038:     Collective

8040:     Input Parameters:
8041: +   mat - the matrix
8042: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8043: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8044: -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8045:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8046:                  always used.

8048:     Output Parameters:
8049: +   n - size of (possibly compressed) matrix
8050: .   ia - the column pointers
8051: .   ja - the row indices
8052: -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned

8054:     Level: developer

8056: .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8057: @*/
8058: PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8059: {
8060:   PetscFunctionBegin;
8066:   MatCheckPreallocated(mat, 1);

8068:   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8069:   else {
8070:     *done = PETSC_TRUE;
8071:     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8072:     if (n) *n = 0;
8073:     if (ia) *ia = NULL;
8074:     if (ja) *ja = NULL;
8075:   }
8076:   PetscFunctionReturn(PETSC_SUCCESS);
8077: }

8079: /*@C
8080:     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.

8082:     Collective

8084:     Input Parameters:
8085: +   mat - the matrix
8086: .   ncolors - max color value
8087: .   n   - number of entries in colorarray
8088: -   colorarray - array indicating color for each column

8090:     Output Parameters:
8091: .   iscoloring - coloring generated using colorarray information

8093:     Level: developer

8095: .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8096: @*/
8097: PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8098: {
8099:   PetscFunctionBegin;
8104:   MatCheckPreallocated(mat, 1);

8106:   if (!mat->ops->coloringpatch) {
8107:     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8108:   } else {
8109:     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8110:   }
8111:   PetscFunctionReturn(PETSC_SUCCESS);
8112: }

8114: /*@
8115:    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.

8117:    Logically Collective

8119:    Input Parameter:
8120: .  mat - the factored matrix to be reset

8122:    Level: developer

8124:    Notes:
8125:    This routine should be used only with factored matrices formed by in-place
8126:    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8127:    format).  This option can save memory, for example, when solving nonlinear
8128:    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8129:    ILU(0) preconditioner.

8131:    One can specify in-place ILU(0) factorization by calling
8132: .vb
8133:      PCType(pc,PCILU);
8134:      PCFactorSeUseInPlace(pc);
8135: .ve
8136:    or by using the options -pc_type ilu -pc_factor_in_place

8138:    In-place factorization ILU(0) can also be used as a local
8139:    solver for the blocks within the block Jacobi or additive Schwarz
8140:    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8141:    for details on setting local solver options.

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

8147: .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8148: @*/
8149: PetscErrorCode MatSetUnfactored(Mat mat)
8150: {
8151:   PetscFunctionBegin;
8154:   MatCheckPreallocated(mat, 1);
8155:   mat->factortype = MAT_FACTOR_NONE;
8156:   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8157:   PetscUseTypeMethod(mat, setunfactored);
8158:   PetscFunctionReturn(PETSC_SUCCESS);
8159: }

8161: /*MC
8162:     MatDenseGetArrayF90 - Accesses a matrix array from Fortran

8164:     Synopsis:
8165:     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)

8167:     Not collective

8169:     Input Parameter:
8170: .   x - matrix

8172:     Output Parameters:
8173: +   xx_v - the Fortran pointer to the array
8174: -   ierr - error code

8176:     Example of Usage:
8177: .vb
8178:       PetscScalar, pointer xx_v(:,:)
8179:       ....
8180:       call MatDenseGetArrayF90(x,xx_v,ierr)
8181:       a = xx_v(3)
8182:       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8183: .ve

8185:     Level: advanced

8187: .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8188: M*/

8190: /*MC
8191:     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8192:     accessed with `MatDenseGetArrayF90()`.

8194:     Synopsis:
8195:     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)

8197:     Not collective

8199:     Input Parameters:
8200: +   x - matrix
8201: -   xx_v - the Fortran90 pointer to the array

8203:     Output Parameter:
8204: .   ierr - error code

8206:     Example of Usage:
8207: .vb
8208:        PetscScalar, pointer xx_v(:,:)
8209:        ....
8210:        call MatDenseGetArrayF90(x,xx_v,ierr)
8211:        a = xx_v(3)
8212:        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8213: .ve

8215:     Level: advanced

8217: .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8218: M*/

8220: /*MC
8221:     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.

8223:     Synopsis:
8224:     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)

8226:     Not collective

8228:     Input Parameter:
8229: .   x - matrix

8231:     Output Parameters:
8232: +   xx_v - the Fortran pointer to the array
8233: -   ierr - error code

8235:     Example of Usage:
8236: .vb
8237:       PetscScalar, pointer xx_v(:)
8238:       ....
8239:       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8240:       a = xx_v(3)
8241:       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8242: .ve

8244:     Level: advanced

8246: .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8247: M*/

8249: /*MC
8250:     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8251:     accessed with `MatSeqAIJGetArrayF90()`.

8253:     Synopsis:
8254:     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)

8256:     Not collective

8258:     Input Parameters:
8259: +   x - matrix
8260: -   xx_v - the Fortran90 pointer to the array

8262:     Output Parameter:
8263: .   ierr - error code

8265:     Example of Usage:
8266: .vb
8267:        PetscScalar, pointer xx_v(:)
8268:        ....
8269:        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8270:        a = xx_v(3)
8271:        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8272: .ve

8274:     Level: advanced

8276: .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8277: M*/

8279: /*@
8280:     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8281:                       as the original matrix.

8283:     Collective

8285:     Input Parameters:
8286: +   mat - the original matrix
8287: .   isrow - parallel IS containing the rows this processor should obtain
8288: .   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.
8289: -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

8291:     Output Parameter:
8292: .   newmat - the new submatrix, of the same type as the old

8294:     Level: advanced

8296:     Notes:
8297:     The submatrix will be able to be multiplied with vectors using the same layout as iscol.

8299:     Some matrix types place restrictions on the row and column indices, such
8300:     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;
8301:     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.

8303:     The index sets may not have duplicate entries.

8305:       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8306:    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8307:    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8308:    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8309:    you are finished using it.

8311:     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8312:     the input matrix.

8314:     If iscol is `NULL` then all columns are obtained (not supported in Fortran).

8316:    Example usage:
8317:    Consider the following 8x8 matrix with 34 non-zero values, that is
8318:    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8319:    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8320:    as follows:

8322: .vb
8323:             1  2  0  |  0  3  0  |  0  4
8324:     Proc0   0  5  6  |  7  0  0  |  8  0
8325:             9  0 10  | 11  0  0  | 12  0
8326:     -------------------------------------
8327:            13  0 14  | 15 16 17  |  0  0
8328:     Proc1   0 18  0  | 19 20 21  |  0  0
8329:             0  0  0  | 22 23  0  | 24  0
8330:     -------------------------------------
8331:     Proc2  25 26 27  |  0  0 28  | 29  0
8332:            30  0  0  | 31 32 33  |  0 34
8333: .ve

8335:     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is

8337: .vb
8338:             2  0  |  0  3  0  |  0
8339:     Proc0   5  6  |  7  0  0  |  8
8340:     -------------------------------
8341:     Proc1  18  0  | 19 20 21  |  0
8342:     -------------------------------
8343:     Proc2  26 27  |  0  0 28  | 29
8344:             0  0  | 31 32 33  |  0
8345: .ve

8347: .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8348: @*/
8349: PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8350: {
8351:   PetscMPIInt size;
8352:   Mat        *local;
8353:   IS          iscoltmp;
8354:   PetscBool   flg;

8356:   PetscFunctionBegin;
8363:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8364:   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");

8366:   MatCheckPreallocated(mat, 1);
8367:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));

8369:   if (!iscol || isrow == iscol) {
8370:     PetscBool   stride;
8371:     PetscMPIInt grabentirematrix = 0, grab;
8372:     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8373:     if (stride) {
8374:       PetscInt first, step, n, rstart, rend;
8375:       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8376:       if (step == 1) {
8377:         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8378:         if (rstart == first) {
8379:           PetscCall(ISGetLocalSize(isrow, &n));
8380:           if (n == rend - rstart) grabentirematrix = 1;
8381:         }
8382:       }
8383:     }
8384:     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8385:     if (grab) {
8386:       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8387:       if (cll == MAT_INITIAL_MATRIX) {
8388:         *newmat = mat;
8389:         PetscCall(PetscObjectReference((PetscObject)mat));
8390:       }
8391:       PetscFunctionReturn(PETSC_SUCCESS);
8392:     }
8393:   }

8395:   if (!iscol) {
8396:     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8397:   } else {
8398:     iscoltmp = iscol;
8399:   }

8401:   /* if original matrix is on just one processor then use submatrix generated */
8402:   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8403:     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8404:     goto setproperties;
8405:   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8406:     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8407:     *newmat = *local;
8408:     PetscCall(PetscFree(local));
8409:     goto setproperties;
8410:   } else if (!mat->ops->createsubmatrix) {
8411:     /* Create a new matrix type that implements the operation using the full matrix */
8412:     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8413:     switch (cll) {
8414:     case MAT_INITIAL_MATRIX:
8415:       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8416:       break;
8417:     case MAT_REUSE_MATRIX:
8418:       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8419:       break;
8420:     default:
8421:       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8422:     }
8423:     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8424:     goto setproperties;
8425:   }

8427:   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8428:   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8429:   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));

8431: setproperties:
8432:   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8433:   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8434:   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8435:   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8436:   PetscFunctionReturn(PETSC_SUCCESS);
8437: }

8439: /*@
8440:    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix

8442:    Not Collective

8444:    Input Parameters:
8445: +  A - the matrix we wish to propagate options from
8446: -  B - the matrix we wish to propagate options to

8448:    Level: beginner

8450:    Note:
8451:    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`

8453: .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8454: @*/
8455: PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8456: {
8457:   PetscFunctionBegin;
8460:   B->symmetry_eternal            = A->symmetry_eternal;
8461:   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8462:   B->symmetric                   = A->symmetric;
8463:   B->structurally_symmetric      = A->structurally_symmetric;
8464:   B->spd                         = A->spd;
8465:   B->hermitian                   = A->hermitian;
8466:   PetscFunctionReturn(PETSC_SUCCESS);
8467: }

8469: /*@
8470:    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8471:    used during the assembly process to store values that belong to
8472:    other processors.

8474:    Not Collective

8476:    Input Parameters:
8477: +  mat   - the matrix
8478: .  size  - the initial size of the stash.
8479: -  bsize - the initial size of the block-stash(if used).

8481:    Options Database Keys:
8482: +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8483: -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>

8485:    Level: intermediate

8487:    Notes:
8488:      The block-stash is used for values set with `MatSetValuesBlocked()` while
8489:      the stash is used for values set with `MatSetValues()`

8491:      Run with the option -info and look for output of the form
8492:      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8493:      to determine the appropriate value, MM, to use for size and
8494:      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8495:      to determine the value, BMM to use for bsize

8497: .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8498: @*/
8499: PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8500: {
8501:   PetscFunctionBegin;
8504:   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8505:   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8506:   PetscFunctionReturn(PETSC_SUCCESS);
8507: }

8509: /*@
8510:    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8511:      the matrix

8513:    Neighbor-wise Collective

8515:    Input Parameters:
8516: +  mat   - the matrix
8517: .  x,y - the vectors
8518: -  w - where the result is stored

8520:    Level: intermediate

8522:    Notes:
8523:     `w` may be the same vector as `y`.

8525:     This allows one to use either the restriction or interpolation (its transpose)
8526:     matrix to do the interpolation

8528: .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8529: @*/
8530: PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8531: {
8532:   PetscInt M, N, Ny;

8534:   PetscFunctionBegin;
8539:   PetscCall(MatGetSize(A, &M, &N));
8540:   PetscCall(VecGetSize(y, &Ny));
8541:   if (M == Ny) {
8542:     PetscCall(MatMultAdd(A, x, y, w));
8543:   } else {
8544:     PetscCall(MatMultTransposeAdd(A, x, y, w));
8545:   }
8546:   PetscFunctionReturn(PETSC_SUCCESS);
8547: }

8549: /*@
8550:    MatInterpolate - y = A*x or A'*x depending on the shape of
8551:      the matrix

8553:    Neighbor-wise Collective

8555:    Input Parameters:
8556: +  mat   - the matrix
8557: -  x,y - the vectors

8559:    Level: intermediate

8561:    Note:
8562:     This allows one to use either the restriction or interpolation (its transpose)
8563:     matrix to do the interpolation

8565: .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8566: @*/
8567: PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8568: {
8569:   PetscInt M, N, Ny;

8571:   PetscFunctionBegin;
8575:   PetscCall(MatGetSize(A, &M, &N));
8576:   PetscCall(VecGetSize(y, &Ny));
8577:   if (M == Ny) {
8578:     PetscCall(MatMult(A, x, y));
8579:   } else {
8580:     PetscCall(MatMultTranspose(A, x, y));
8581:   }
8582:   PetscFunctionReturn(PETSC_SUCCESS);
8583: }

8585: /*@
8586:    MatRestrict - y = A*x or A'*x

8588:    Neighbor-wise Collective

8590:    Input Parameters:
8591: +  mat   - the matrix
8592: -  x,y - the vectors

8594:    Level: intermediate

8596:    Note:
8597:     This allows one to use either the restriction or interpolation (its transpose)
8598:     matrix to do the restriction

8600: .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8601: @*/
8602: PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8603: {
8604:   PetscInt M, N, Ny;

8606:   PetscFunctionBegin;
8610:   PetscCall(MatGetSize(A, &M, &N));
8611:   PetscCall(VecGetSize(y, &Ny));
8612:   if (M == Ny) {
8613:     PetscCall(MatMult(A, x, y));
8614:   } else {
8615:     PetscCall(MatMultTranspose(A, x, y));
8616:   }
8617:   PetscFunctionReturn(PETSC_SUCCESS);
8618: }

8620: /*@
8621:    MatMatInterpolateAdd - Y = W + A*X or W + A'*X

8623:    Neighbor-wise Collective

8625:    Input Parameters:
8626: +  mat   - the matrix
8627: -  w, x - the input dense matrices

8629:    Output Parameters:
8630: .  y - the output dense matrix

8632:    Level: intermediate

8634:    Note:
8635:     This allows one to use either the restriction or interpolation (its transpose)
8636:     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8637:     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.

8639: .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8640: @*/
8641: PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8642: {
8643:   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8644:   PetscBool trans = PETSC_TRUE;
8645:   MatReuse  reuse = MAT_INITIAL_MATRIX;

8647:   PetscFunctionBegin;
8653:   PetscCall(MatGetSize(A, &M, &N));
8654:   PetscCall(MatGetSize(x, &Mx, &Nx));
8655:   if (N == Mx) trans = PETSC_FALSE;
8656:   else PetscCheck(M == Mx, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Size mismatch: A %" PetscInt_FMT "x%" PetscInt_FMT ", X %" PetscInt_FMT "x%" PetscInt_FMT, M, N, Mx, Nx);
8657:   Mo = trans ? N : M;
8658:   if (*y) {
8659:     PetscCall(MatGetSize(*y, &My, &Ny));
8660:     if (Mo == My && Nx == Ny) {
8661:       reuse = MAT_REUSE_MATRIX;
8662:     } else {
8663:       PetscCheck(w || *y != w, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot reuse y and w, size mismatch: A %" PetscInt_FMT "x%" PetscInt_FMT ", X %" PetscInt_FMT "x%" PetscInt_FMT ", Y %" PetscInt_FMT "x%" PetscInt_FMT, M, N, Mx, Nx, My, Ny);
8664:       PetscCall(MatDestroy(y));
8665:     }
8666:   }

8668:   if (w && *y == w) { /* this is to minimize changes in PCMG */
8669:     PetscBool flg;

8671:     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8672:     if (w) {
8673:       PetscInt My, Ny, Mw, Nw;

8675:       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8676:       PetscCall(MatGetSize(*y, &My, &Ny));
8677:       PetscCall(MatGetSize(w, &Mw, &Nw));
8678:       if (!flg || My != Mw || Ny != Nw) w = NULL;
8679:     }
8680:     if (!w) {
8681:       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8682:       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8683:       PetscCall(PetscObjectDereference((PetscObject)w));
8684:     } else {
8685:       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8686:     }
8687:   }
8688:   if (!trans) {
8689:     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8690:   } else {
8691:     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8692:   }
8693:   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8694:   PetscFunctionReturn(PETSC_SUCCESS);
8695: }

8697: /*@
8698:    MatMatInterpolate - Y = A*X or A'*X

8700:    Neighbor-wise Collective

8702:    Input Parameters:
8703: +  mat   - the matrix
8704: -  x - the input dense matrix

8706:    Output Parameters:
8707: .  y - the output dense matrix

8709:    Level: intermediate

8711:    Note:
8712:     This allows one to use either the restriction or interpolation (its transpose)
8713:     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8714:     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.

8716: .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8717: @*/
8718: PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8719: {
8720:   PetscFunctionBegin;
8721:   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8722:   PetscFunctionReturn(PETSC_SUCCESS);
8723: }

8725: /*@
8726:    MatMatRestrict - Y = A*X or A'*X

8728:    Neighbor-wise Collective

8730:    Input Parameters:
8731: +  mat   - the matrix
8732: -  x - the input dense matrix

8734:    Output Parameters:
8735: .  y - the output dense matrix

8737:    Level: intermediate

8739:    Note:
8740:     This allows one to use either the restriction or interpolation (its transpose)
8741:     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8742:     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.

8744: .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8745: @*/
8746: PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8747: {
8748:   PetscFunctionBegin;
8749:   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8750:   PetscFunctionReturn(PETSC_SUCCESS);
8751: }

8753: /*@
8754:    MatGetNullSpace - retrieves the null space of a matrix.

8756:    Logically Collective

8758:    Input Parameters:
8759: +  mat - the matrix
8760: -  nullsp - the null space object

8762:    Level: developer

8764: .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8765: @*/
8766: PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8767: {
8768:   PetscFunctionBegin;
8771:   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8772:   PetscFunctionReturn(PETSC_SUCCESS);
8773: }

8775: /*@
8776:    MatSetNullSpace - attaches a null space to a matrix.

8778:    Logically Collective

8780:    Input Parameters:
8781: +  mat - the matrix
8782: -  nullsp - the null space object

8784:    Level: advanced

8786:    Notes:
8787:       This null space is used by the `KSP` linear solvers to solve singular systems.

8789:       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`

8791:       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
8792:       to zero but the linear system will still be solved in a least squares sense.

8794:       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8795:    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).
8796:    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
8797:    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
8798:    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).
8799:    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.

8801:     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8802:     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8803:     routine also automatically calls `MatSetTransposeNullSpace()`.

8805:     The user should call `MatNullSpaceDestroy()`.

8807: .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8808:           `KSPSetPCSide()`
8809: @*/
8810: PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8811: {
8812:   PetscFunctionBegin;
8815:   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8816:   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8817:   mat->nullsp = nullsp;
8818:   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8819:   PetscFunctionReturn(PETSC_SUCCESS);
8820: }

8822: /*@
8823:    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.

8825:    Logically Collective

8827:    Input Parameters:
8828: +  mat - the matrix
8829: -  nullsp - the null space object

8831:    Level: developer

8833: .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8834: @*/
8835: PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8836: {
8837:   PetscFunctionBegin;
8841:   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8842:   PetscFunctionReturn(PETSC_SUCCESS);
8843: }

8845: /*@
8846:    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix

8848:    Logically Collective

8850:    Input Parameters:
8851: +  mat - the matrix
8852: -  nullsp - the null space object

8854:    Level: advanced

8856:    Notes:
8857:    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.

8859:    See `MatSetNullSpace()`

8861: .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8862: @*/
8863: PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8864: {
8865:   PetscFunctionBegin;
8868:   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8869:   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8870:   mat->transnullsp = nullsp;
8871:   PetscFunctionReturn(PETSC_SUCCESS);
8872: }

8874: /*@
8875:    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8876:         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.

8878:    Logically Collective

8880:    Input Parameters:
8881: +  mat - the matrix
8882: -  nullsp - the null space object

8884:    Level: advanced

8886:    Notes:
8887:    Overwrites any previous near null space that may have been attached

8889:    You can remove the null space by calling this routine with an nullsp of `NULL`

8891: .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8892: @*/
8893: PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8894: {
8895:   PetscFunctionBegin;
8899:   MatCheckPreallocated(mat, 1);
8900:   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8901:   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8902:   mat->nearnullsp = nullsp;
8903:   PetscFunctionReturn(PETSC_SUCCESS);
8904: }

8906: /*@
8907:    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`

8909:    Not Collective

8911:    Input Parameter:
8912: .  mat - the matrix

8914:    Output Parameter:
8915: .  nullsp - the null space object, `NULL` if not set

8917:    Level: advanced

8919: .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8920: @*/
8921: PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8922: {
8923:   PetscFunctionBegin;
8927:   MatCheckPreallocated(mat, 1);
8928:   *nullsp = mat->nearnullsp;
8929:   PetscFunctionReturn(PETSC_SUCCESS);
8930: }

8932: /*@C
8933:    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.

8935:    Collective

8937:    Input Parameters:
8938: +  mat - the matrix
8939: .  row - row/column permutation
8940: .  fill - expected fill factor >= 1.0
8941: -  level - level of fill, for ICC(k)

8943:    Notes:
8944:    Probably really in-place only when level of fill is zero, otherwise allocates
8945:    new space to store factored matrix and deletes previous memory.

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

8951:    Level: developer

8953:    Developer Note:
8954:    The Fortran interface is not autogenerated as the
8955:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

8957: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8958: @*/
8959: PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8960: {
8961:   PetscFunctionBegin;
8966:   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8967:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8968:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8969:   MatCheckPreallocated(mat, 1);
8970:   PetscUseTypeMethod(mat, iccfactor, row, info);
8971:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8972:   PetscFunctionReturn(PETSC_SUCCESS);
8973: }

8975: /*@
8976:    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8977:          ghosted ones.

8979:    Not Collective

8981:    Input Parameters:
8982: +  mat - the matrix
8983: -  diag - the diagonal values, including ghost ones

8985:    Level: developer

8987:    Notes:
8988:     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices

8990:     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`

8992: .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
8993: @*/
8994: PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8995: {
8996:   PetscMPIInt size;

8998:   PetscFunctionBegin;

9003:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9004:   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9005:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9006:   if (size == 1) {
9007:     PetscInt n, m;
9008:     PetscCall(VecGetSize(diag, &n));
9009:     PetscCall(MatGetSize(mat, NULL, &m));
9010:     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9011:     PetscCall(MatDiagonalScale(mat, NULL, diag));
9012:   } else {
9013:     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9014:   }
9015:   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9016:   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9017:   PetscFunctionReturn(PETSC_SUCCESS);
9018: }

9020: /*@
9021:    MatGetInertia - Gets the inertia from a factored matrix

9023:    Collective

9025:    Input Parameter:
9026: .  mat - the matrix

9028:    Output Parameters:
9029: +   nneg - number of negative eigenvalues
9030: .   nzero - number of zero eigenvalues
9031: -   npos - number of positive eigenvalues

9033:    Level: advanced

9035:    Note:
9036:     Matrix must have been factored by `MatCholeskyFactor()`

9038: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9039: @*/
9040: PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9041: {
9042:   PetscFunctionBegin;
9045:   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9046:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9047:   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9048:   PetscFunctionReturn(PETSC_SUCCESS);
9049: }

9051: /*@C
9052:    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors

9054:    Neighbor-wise Collective

9056:    Input Parameters:
9057: +  mat - the factored matrix obtained with `MatGetFactor()`
9058: -  b - the right-hand-side vectors

9060:    Output Parameter:
9061: .  x - the result vectors

9063:    Level: developer

9065:    Note:
9066:    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9067:    call `MatSolves`(A,x,x).

9069: .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9070: @*/
9071: PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9072: {
9073:   PetscFunctionBegin;
9076:   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9077:   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9078:   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);

9080:   MatCheckPreallocated(mat, 1);
9081:   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9082:   PetscUseTypeMethod(mat, solves, b, x);
9083:   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9084:   PetscFunctionReturn(PETSC_SUCCESS);
9085: }

9087: /*@
9088:    MatIsSymmetric - Test whether a matrix is symmetric

9090:    Collective

9092:    Input Parameters:
9093: +  A - the matrix to test
9094: -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)

9096:    Output Parameters:
9097: .  flg - the result

9099:    Level: intermediate

9101:    Notes:
9102:     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results

9104:     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`

9106:     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9107:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9109: .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9110:           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9111: @*/
9112: PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9113: {
9114:   PetscFunctionBegin;

9118:   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9119:   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9120:   else {
9121:     if (!A->ops->issymmetric) {
9122:       MatType mattype;
9123:       PetscCall(MatGetType(A, &mattype));
9124:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
9125:     }
9126:     PetscUseTypeMethod(A, issymmetric, tol, flg);
9127:     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9128:   }
9129:   PetscFunctionReturn(PETSC_SUCCESS);
9130: }

9132: /*@
9133:    MatIsHermitian - Test whether a matrix is Hermitian

9135:    Collective

9137:    Input Parameters:
9138: +  A - the matrix to test
9139: -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)

9141:    Output Parameters:
9142: .  flg - the result

9144:    Level: intermediate

9146:    Notes:
9147:     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results

9149:     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`

9151:     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9152:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)

9154: .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9155:           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9156: @*/
9157: PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9158: {
9159:   PetscFunctionBegin;

9163:   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9164:   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9165:   else {
9166:     if (!A->ops->ishermitian) {
9167:       MatType mattype;
9168:       PetscCall(MatGetType(A, &mattype));
9169:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
9170:     }
9171:     PetscUseTypeMethod(A, ishermitian, tol, flg);
9172:     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9173:   }
9174:   PetscFunctionReturn(PETSC_SUCCESS);
9175: }

9177: /*@
9178:    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state

9180:    Not Collective

9182:    Input Parameter:
9183: .  A - the matrix to check

9185:    Output Parameters:
9186: +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9187: -  flg - the result (only valid if set is `PETSC_TRUE`)

9189:    Level: advanced

9191:    Notes:
9192:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9193:    if you want it explicitly checked

9195:     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9196:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9198: .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9199: @*/
9200: PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9201: {
9202:   PetscFunctionBegin;
9206:   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9207:     *set = PETSC_TRUE;
9208:     *flg = PetscBool3ToBool(A->symmetric);
9209:   } else {
9210:     *set = PETSC_FALSE;
9211:   }
9212:   PetscFunctionReturn(PETSC_SUCCESS);
9213: }

9215: /*@
9216:    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state

9218:    Not Collective

9220:    Input Parameter:
9221: .  A - the matrix to check

9223:    Output Parameters:
9224: +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9225: -  flg - the result (only valid if set is `PETSC_TRUE`)

9227:    Level: advanced

9229:    Notes:
9230:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).

9232:    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9233:    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)

9235: .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9236: @*/
9237: PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9238: {
9239:   PetscFunctionBegin;
9243:   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9244:     *set = PETSC_TRUE;
9245:     *flg = PetscBool3ToBool(A->spd);
9246:   } else {
9247:     *set = PETSC_FALSE;
9248:   }
9249:   PetscFunctionReturn(PETSC_SUCCESS);
9250: }

9252: /*@
9253:    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state

9255:    Not Collective

9257:    Input Parameter:
9258: .  A - the matrix to check

9260:    Output Parameters:
9261: +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9262: -  flg - the result (only valid if set is `PETSC_TRUE`)

9264:    Level: advanced

9266:    Notes:
9267:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9268:    if you want it explicitly checked

9270:    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9271:    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9273: .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9274: @*/
9275: PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9276: {
9277:   PetscFunctionBegin;
9281:   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9282:     *set = PETSC_TRUE;
9283:     *flg = PetscBool3ToBool(A->hermitian);
9284:   } else {
9285:     *set = PETSC_FALSE;
9286:   }
9287:   PetscFunctionReturn(PETSC_SUCCESS);
9288: }

9290: /*@
9291:    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric

9293:    Collective

9295:    Input Parameter:
9296: .  A - the matrix to test

9298:    Output Parameters:
9299: .  flg - the result

9301:    Level: intermediate

9303:    Notes:
9304:    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`

9306:    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
9307:    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9309: .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9310: @*/
9311: PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9312: {
9313:   PetscFunctionBegin;
9316:   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9317:     *flg = PetscBool3ToBool(A->structurally_symmetric);
9318:   } else {
9319:     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9320:     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9321:   }
9322:   PetscFunctionReturn(PETSC_SUCCESS);
9323: }

9325: /*@
9326:    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state

9328:    Not Collective

9330:    Input Parameter:
9331: .  A - the matrix to check

9333:    Output Parameters:
9334: +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9335: -  flg - the result (only valid if set is PETSC_TRUE)

9337:    Level: advanced

9339:    Notes:
9340:    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
9341:    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9343:    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)

9345: .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9346: @*/
9347: PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9348: {
9349:   PetscFunctionBegin;
9353:   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9354:     *set = PETSC_TRUE;
9355:     *flg = PetscBool3ToBool(A->structurally_symmetric);
9356:   } else {
9357:     *set = PETSC_FALSE;
9358:   }
9359:   PetscFunctionReturn(PETSC_SUCCESS);
9360: }

9362: /*@
9363:    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9364:        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process

9366:     Not collective

9368:    Input Parameter:
9369: .   mat - the matrix

9371:    Output Parameters:
9372: +   nstash   - the size of the stash
9373: .   reallocs - the number of additional mallocs incurred.
9374: .   bnstash   - the size of the block stash
9375: -   breallocs - the number of additional mallocs incurred.in the block stash

9377:    Level: advanced

9379: .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9380: @*/
9381: PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9382: {
9383:   PetscFunctionBegin;
9384:   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9385:   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9386:   PetscFunctionReturn(PETSC_SUCCESS);
9387: }

9389: /*@C
9390:    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9391:    parallel layout, `PetscLayout` for rows and columns

9393:    Collective

9395:    Input Parameter:
9396: .  mat - the matrix

9398:    Output Parameters:
9399: +   right - (optional) vector that the matrix can be multiplied against
9400: -   left - (optional) vector that the matrix vector product can be stored in

9402:   Level: advanced

9404:    Notes:
9405:     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()`.

9407:     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed

9409: .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9410: @*/
9411: PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9412: {
9413:   PetscFunctionBegin;
9416:   if (mat->ops->getvecs) {
9417:     PetscUseTypeMethod(mat, getvecs, right, left);
9418:   } else {
9419:     PetscInt rbs, cbs;
9420:     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9421:     if (right) {
9422:       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9423:       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9424:       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9425:       PetscCall(VecSetBlockSize(*right, cbs));
9426:       PetscCall(VecSetType(*right, mat->defaultvectype));
9427: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9428:       if (mat->boundtocpu && mat->bindingpropagates) {
9429:         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9430:         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9431:       }
9432: #endif
9433:       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9434:     }
9435:     if (left) {
9436:       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9437:       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9438:       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9439:       PetscCall(VecSetBlockSize(*left, rbs));
9440:       PetscCall(VecSetType(*left, mat->defaultvectype));
9441: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9442:       if (mat->boundtocpu && mat->bindingpropagates) {
9443:         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9444:         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9445:       }
9446: #endif
9447:       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9448:     }
9449:   }
9450:   PetscFunctionReturn(PETSC_SUCCESS);
9451: }

9453: /*@C
9454:    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9455:      with default values.

9457:    Not Collective

9459:    Input Parameters:
9460: .    info - the `MatFactorInfo` data structure

9462:    Level: developer

9464:    Notes:
9465:     The solvers are generally used through the `KSP` and `PC` objects, for example
9466:           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`

9468:     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed

9470:    Developer Note:
9471:    The Fortran interface is not autogenerated as the
9472:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

9474: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9475: @*/
9476: PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9477: {
9478:   PetscFunctionBegin;
9479:   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9480:   PetscFunctionReturn(PETSC_SUCCESS);
9481: }

9483: /*@
9484:    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed

9486:    Collective

9488:    Input Parameters:
9489: +  mat - the factored matrix
9490: -  is - the index set defining the Schur indices (0-based)

9492:    Level: advanced

9494:    Notes:
9495:     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.

9497:    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.

9499:    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`

9501: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9502:           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9503: @*/
9504: PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9505: {
9506:   PetscErrorCode (*f)(Mat, IS);

9508:   PetscFunctionBegin;
9513:   PetscCheckSameComm(mat, 1, is, 2);
9514:   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9515:   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9516:   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9517:   PetscCall(MatDestroy(&mat->schur));
9518:   PetscCall((*f)(mat, is));
9519:   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9520:   PetscFunctionReturn(PETSC_SUCCESS);
9521: }

9523: /*@
9524:   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step

9526:    Logically Collective

9528:    Input Parameters:
9529: +  F - the factored matrix obtained by calling `MatGetFactor()`
9530: .  S - location where to return the Schur complement, can be `NULL`
9531: -  status - the status of the Schur complement matrix, can be `NULL`

9533:    Level: advanced

9535:    Notes:
9536:    You must call `MatFactorSetSchurIS()` before calling this routine.

9538:    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`

9540:    The routine provides a copy of the Schur matrix stored within the solver data structures.
9541:    The caller must destroy the object when it is no longer needed.
9542:    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.

9544:    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)

9546:    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.

9548:    Developer Note:
9549:     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9550:    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.

9552: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9553: @*/
9554: PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9555: {
9556:   PetscFunctionBegin;
9560:   if (S) {
9561:     PetscErrorCode (*f)(Mat, Mat *);

9563:     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9564:     if (f) {
9565:       PetscCall((*f)(F, S));
9566:     } else {
9567:       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9568:     }
9569:   }
9570:   if (status) *status = F->schur_status;
9571:   PetscFunctionReturn(PETSC_SUCCESS);
9572: }

9574: /*@
9575:   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix

9577:    Logically Collective

9579:    Input Parameters:
9580: +  F - the factored matrix obtained by calling `MatGetFactor()`
9581: .  *S - location where to return the Schur complement, can be `NULL`
9582: -  status - the status of the Schur complement matrix, can be `NULL`

9584:    Level: advanced

9586:    Notes:
9587:    You must call `MatFactorSetSchurIS()` before calling this routine.

9589:    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`

9591:    The routine returns a the Schur Complement stored within the data structures of the solver.

9593:    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.

9595:    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.

9597:    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix

9599:    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.

9601: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9602: @*/
9603: PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9604: {
9605:   PetscFunctionBegin;
9609:   if (S) *S = F->schur;
9610:   if (status) *status = F->schur_status;
9611:   PetscFunctionReturn(PETSC_SUCCESS);
9612: }

9614: static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9615: {
9616:   Mat S = F->schur;

9618:   PetscFunctionBegin;
9619:   switch (F->schur_status) {
9620:   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9621:   case MAT_FACTOR_SCHUR_INVERTED:
9622:     if (S) {
9623:       S->ops->solve             = NULL;
9624:       S->ops->matsolve          = NULL;
9625:       S->ops->solvetranspose    = NULL;
9626:       S->ops->matsolvetranspose = NULL;
9627:       S->ops->solveadd          = NULL;
9628:       S->ops->solvetransposeadd = NULL;
9629:       S->factortype             = MAT_FACTOR_NONE;
9630:       PetscCall(PetscFree(S->solvertype));
9631:     }
9632:   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9633:     break;
9634:   default:
9635:     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9636:   }
9637:   PetscFunctionReturn(PETSC_SUCCESS);
9638: }

9640: /*@
9641:   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`

9643:    Logically Collective

9645:    Input Parameters:
9646: +  F - the factored matrix obtained by calling `MatGetFactor()`
9647: .  *S - location where the Schur complement is stored
9648: -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)

9650:    Level: advanced

9652: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9653: @*/
9654: PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9655: {
9656:   PetscFunctionBegin;
9658:   if (S) {
9660:     *S = NULL;
9661:   }
9662:   F->schur_status = status;
9663:   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9664:   PetscFunctionReturn(PETSC_SUCCESS);
9665: }

9667: /*@
9668:   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step

9670:    Logically Collective

9672:    Input Parameters:
9673: +  F - the factored matrix obtained by calling `MatGetFactor()`
9674: .  rhs - location where the right hand side of the Schur complement system is stored
9675: -  sol - location where the solution of the Schur complement system has to be returned

9677:    Level: advanced

9679:    Notes:
9680:    The sizes of the vectors should match the size of the Schur complement

9682:    Must be called after `MatFactorSetSchurIS()`

9684: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9685: @*/
9686: PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9687: {
9688:   PetscFunctionBegin;
9695:   PetscCheckSameComm(F, 1, rhs, 2);
9696:   PetscCheckSameComm(F, 1, sol, 3);
9697:   PetscCall(MatFactorFactorizeSchurComplement(F));
9698:   switch (F->schur_status) {
9699:   case MAT_FACTOR_SCHUR_FACTORED:
9700:     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9701:     break;
9702:   case MAT_FACTOR_SCHUR_INVERTED:
9703:     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9704:     break;
9705:   default:
9706:     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9707:   }
9708:   PetscFunctionReturn(PETSC_SUCCESS);
9709: }

9711: /*@
9712:   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step

9714:    Logically Collective

9716:    Input Parameters:
9717: +  F - the factored matrix obtained by calling `MatGetFactor()`
9718: .  rhs - location where the right hand side of the Schur complement system is stored
9719: -  sol - location where the solution of the Schur complement system has to be returned

9721:    Level: advanced

9723:    Notes:
9724:    The sizes of the vectors should match the size of the Schur complement

9726:    Must be called after `MatFactorSetSchurIS()`

9728: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9729: @*/
9730: PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9731: {
9732:   PetscFunctionBegin;
9739:   PetscCheckSameComm(F, 1, rhs, 2);
9740:   PetscCheckSameComm(F, 1, sol, 3);
9741:   PetscCall(MatFactorFactorizeSchurComplement(F));
9742:   switch (F->schur_status) {
9743:   case MAT_FACTOR_SCHUR_FACTORED:
9744:     PetscCall(MatSolve(F->schur, rhs, sol));
9745:     break;
9746:   case MAT_FACTOR_SCHUR_INVERTED:
9747:     PetscCall(MatMult(F->schur, rhs, sol));
9748:     break;
9749:   default:
9750:     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9751:   }
9752:   PetscFunctionReturn(PETSC_SUCCESS);
9753: }

9755: PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9756: #if PetscDefined(HAVE_CUDA)
9757: PETSC_EXTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Private(Mat);
9758: #endif

9760: /* Schur status updated in the interface */
9761: static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9762: {
9763:   Mat S = F->schur;

9765:   PetscFunctionBegin;
9766:   if (S) {
9767:     PetscMPIInt size;
9768:     PetscBool   isdense, isdensecuda;

9770:     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9771:     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9772:     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9773:     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9774:     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9775:     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9776:     if (isdense) {
9777:       PetscCall(MatSeqDenseInvertFactors_Private(S));
9778:     } else if (isdensecuda) {
9779: #if defined(PETSC_HAVE_CUDA)
9780:       PetscCall(MatSeqDenseCUDAInvertFactors_Private(S));
9781: #endif
9782:     }
9783:     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9784:   }
9785:   PetscFunctionReturn(PETSC_SUCCESS);
9786: }

9788: /*@
9789:   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step

9791:    Logically Collective

9793:    Input Parameters:
9794: .  F - the factored matrix obtained by calling `MatGetFactor()`

9796:    Level: advanced

9798:    Notes:
9799:     Must be called after `MatFactorSetSchurIS()`.

9801:    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.

9803: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9804: @*/
9805: PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9806: {
9807:   PetscFunctionBegin;
9810:   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9811:   PetscCall(MatFactorFactorizeSchurComplement(F));
9812:   PetscCall(MatFactorInvertSchurComplement_Private(F));
9813:   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9814:   PetscFunctionReturn(PETSC_SUCCESS);
9815: }

9817: /*@
9818:   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step

9820:    Logically Collective

9822:    Input Parameters:
9823: .  F - the factored matrix obtained by calling `MatGetFactor()`

9825:    Level: advanced

9827:    Note:
9828:     Must be called after `MatFactorSetSchurIS()`

9830: .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9831: @*/
9832: PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9833: {
9834:   MatFactorInfo info;

9836:   PetscFunctionBegin;
9839:   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9840:   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9841:   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9842:     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9843:   } else {
9844:     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9845:   }
9846:   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9847:   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9848:   PetscFunctionReturn(PETSC_SUCCESS);
9849: }

9851: /*@
9852:    MatPtAP - Creates the matrix product C = P^T * A * P

9854:    Neighbor-wise Collective

9856:    Input Parameters:
9857: +  A - the matrix
9858: .  P - the projection matrix
9859: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9860: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9861:           if the result is a dense matrix this is irrelevant

9863:    Output Parameters:
9864: .  C - the product matrix

9866:    Level: intermediate

9868:    Notes:
9869:    C will be created and must be destroyed by the user with `MatDestroy()`.

9871:    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done

9873:    Developer Note:
9874:    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.

9876: .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9877: @*/
9878: PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9879: {
9880:   PetscFunctionBegin;
9881:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9882:   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");

9884:   if (scall == MAT_INITIAL_MATRIX) {
9885:     PetscCall(MatProductCreate(A, P, NULL, C));
9886:     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9887:     PetscCall(MatProductSetAlgorithm(*C, "default"));
9888:     PetscCall(MatProductSetFill(*C, fill));

9890:     (*C)->product->api_user = PETSC_TRUE;
9891:     PetscCall(MatProductSetFromOptions(*C));
9892:     PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for A %s and P %s", MatProductTypes[MATPRODUCT_PtAP], ((PetscObject)A)->type_name, ((PetscObject)P)->type_name);
9893:     PetscCall(MatProductSymbolic(*C));
9894:   } else { /* scall == MAT_REUSE_MATRIX */
9895:     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9896:   }

9898:   PetscCall(MatProductNumeric(*C));
9899:   (*C)->symmetric = A->symmetric;
9900:   (*C)->spd       = A->spd;
9901:   PetscFunctionReturn(PETSC_SUCCESS);
9902: }

9904: /*@
9905:    MatRARt - Creates the matrix product C = R * A * R^T

9907:    Neighbor-wise Collective

9909:    Input Parameters:
9910: +  A - the matrix
9911: .  R - the projection matrix
9912: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9913: -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9914:           if the result is a dense matrix this is irrelevant

9916:    Output Parameters:
9917: .  C - the product matrix

9919:    Level: intermediate

9921:    Notes:
9922:    C will be created and must be destroyed by the user with `MatDestroy()`.

9924:    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done

9926:    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9927:    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9928:    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9929:    We recommend using MatPtAP().

9931: .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9932: @*/
9933: PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9934: {
9935:   PetscFunctionBegin;
9936:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9937:   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");

9939:   if (scall == MAT_INITIAL_MATRIX) {
9940:     PetscCall(MatProductCreate(A, R, NULL, C));
9941:     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9942:     PetscCall(MatProductSetAlgorithm(*C, "default"));
9943:     PetscCall(MatProductSetFill(*C, fill));

9945:     (*C)->product->api_user = PETSC_TRUE;
9946:     PetscCall(MatProductSetFromOptions(*C));
9947:     PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for A %s and R %s", MatProductTypes[MATPRODUCT_RARt], ((PetscObject)A)->type_name, ((PetscObject)R)->type_name);
9948:     PetscCall(MatProductSymbolic(*C));
9949:   } else { /* scall == MAT_REUSE_MATRIX */
9950:     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9951:   }

9953:   PetscCall(MatProductNumeric(*C));
9954:   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9955:   PetscFunctionReturn(PETSC_SUCCESS);
9956: }

9958: static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9959: {
9960:   PetscFunctionBegin;
9961:   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");

9963:   if (scall == MAT_INITIAL_MATRIX) {
9964:     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9965:     PetscCall(MatProductCreate(A, B, NULL, C));
9966:     PetscCall(MatProductSetType(*C, ptype));
9967:     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9968:     PetscCall(MatProductSetFill(*C, fill));

9970:     (*C)->product->api_user = PETSC_TRUE;
9971:     PetscCall(MatProductSetFromOptions(*C));
9972:     PetscCall(MatProductSymbolic(*C));
9973:   } else { /* scall == MAT_REUSE_MATRIX */
9974:     Mat_Product *product = (*C)->product;
9975:     PetscBool    isdense;

9977:     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9978:     if (isdense && product && product->type != ptype) {
9979:       PetscCall(MatProductClear(*C));
9980:       product = NULL;
9981:     }
9982:     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9983:     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9984:       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9985:       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9986:       product           = (*C)->product;
9987:       product->fill     = fill;
9988:       product->api_user = PETSC_TRUE;
9989:       product->clear    = PETSC_TRUE;

9991:       PetscCall(MatProductSetType(*C, ptype));
9992:       PetscCall(MatProductSetFromOptions(*C));
9993:       PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for %s and %s", MatProductTypes[ptype], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name);
9994:       PetscCall(MatProductSymbolic(*C));
9995:     } else { /* user may change input matrices A or B when REUSE */
9996:       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9997:     }
9998:   }
9999:   PetscCall(MatProductNumeric(*C));
10000:   PetscFunctionReturn(PETSC_SUCCESS);
10001: }

10003: /*@
10004:    MatMatMult - Performs matrix-matrix multiplication C=A*B.

10006:    Neighbor-wise Collective

10008:    Input Parameters:
10009: +  A - the left matrix
10010: .  B - the right matrix
10011: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10012: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10013:           if the result is a dense matrix this is irrelevant

10015:    Output Parameters:
10016: .  C - the product matrix

10018:    Notes:
10019:    Unless scall is `MAT_REUSE_MATRIX` C will be created.

10021:    `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
10022:    call to this function with `MAT_INITIAL_MATRIX`.

10024:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.

10026:    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`,
10027:    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.

10029:    Example of Usage:
10030: .vb
10031:      MatProductCreate(A,B,NULL,&C);
10032:      MatProductSetType(C,MATPRODUCT_AB);
10033:      MatProductSymbolic(C);
10034:      MatProductNumeric(C); // compute C=A * B
10035:      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10036:      MatProductNumeric(C);
10037:      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10038:      MatProductNumeric(C);
10039: .ve

10041:    Level: intermediate

10043: .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10044: @*/
10045: PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10046: {
10047:   PetscFunctionBegin;
10048:   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10049:   PetscFunctionReturn(PETSC_SUCCESS);
10050: }

10052: /*@
10053:    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.

10055:    Neighbor-wise Collective

10057:    Input Parameters:
10058: +  A - the left matrix
10059: .  B - the right matrix
10060: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10061: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known

10063:    Output Parameters:
10064: .  C - the product matrix

10066:    Level: intermediate

10068:    Notes:
10069:    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.

10071:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call

10073:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10074:    actually needed.

10076:    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10077:    and for pairs of `MATMPIDENSE` matrices.

10079:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`

10081:    Options Database Keys:
10082: .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10083:               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10084:               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.

10086: .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10087: @*/
10088: PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10089: {
10090:   PetscFunctionBegin;
10091:   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10092:   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10093:   PetscFunctionReturn(PETSC_SUCCESS);
10094: }

10096: /*@
10097:    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.

10099:    Neighbor-wise Collective

10101:    Input Parameters:
10102: +  A - the left matrix
10103: .  B - the right matrix
10104: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10105: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known

10107:    Output Parameters:
10108: .  C - the product matrix

10110:    Level: intermediate

10112:    Notes:
10113:    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.

10115:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.

10117:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`

10119:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10120:    actually needed.

10122:    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10123:    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.

10125: .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10126: @*/
10127: PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10128: {
10129:   PetscFunctionBegin;
10130:   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10131:   PetscFunctionReturn(PETSC_SUCCESS);
10132: }

10134: /*@
10135:    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.

10137:    Neighbor-wise Collective

10139:    Input Parameters:
10140: +  A - the left matrix
10141: .  B - the middle matrix
10142: .  C - the right matrix
10143: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10144: -  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
10145:           if the result is a dense matrix this is irrelevant

10147:    Output Parameters:
10148: .  D - the product matrix

10150:    Level: intermediate

10152:    Notes:
10153:    Unless scall is `MAT_REUSE_MATRIX` D will be created.

10155:    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call

10157:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`

10159:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10160:    actually needed.

10162:    If you have many matrices with the same non-zero structure to multiply, you
10163:    should use `MAT_REUSE_MATRIX` in all calls but the first

10165: .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10166: @*/
10167: PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10168: {
10169:   PetscFunctionBegin;
10170:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10171:   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");

10173:   if (scall == MAT_INITIAL_MATRIX) {
10174:     PetscCall(MatProductCreate(A, B, C, D));
10175:     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10176:     PetscCall(MatProductSetAlgorithm(*D, "default"));
10177:     PetscCall(MatProductSetFill(*D, fill));

10179:     (*D)->product->api_user = PETSC_TRUE;
10180:     PetscCall(MatProductSetFromOptions(*D));
10181:     PetscCheck((*D)->ops->productsymbolic, PetscObjectComm((PetscObject)(*D)), PETSC_ERR_SUP, "MatProduct %s not supported for A %s, B %s and C %s", MatProductTypes[MATPRODUCT_ABC], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name,
10182:                ((PetscObject)C)->type_name);
10183:     PetscCall(MatProductSymbolic(*D));
10184:   } else { /* user may change input matrices when REUSE */
10185:     PetscCall(MatProductReplaceMats(A, B, C, *D));
10186:   }
10187:   PetscCall(MatProductNumeric(*D));
10188:   PetscFunctionReturn(PETSC_SUCCESS);
10189: }

10191: /*@
10192:    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.

10194:    Collective

10196:    Input Parameters:
10197: +  mat - the matrix
10198: .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10199: .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10200: -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

10202:    Output Parameter:
10203: .  matredundant - redundant matrix

10205:    Level: advanced

10207:    Notes:
10208:    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10209:    original matrix has not changed from that last call to MatCreateRedundantMatrix().

10211:    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10212:    calling it.

10214:    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.

10216: .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10217: @*/
10218: PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10219: {
10220:   MPI_Comm       comm;
10221:   PetscMPIInt    size;
10222:   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10223:   Mat_Redundant *redund     = NULL;
10224:   PetscSubcomm   psubcomm   = NULL;
10225:   MPI_Comm       subcomm_in = subcomm;
10226:   Mat           *matseq;
10227:   IS             isrow, iscol;
10228:   PetscBool      newsubcomm = PETSC_FALSE;

10230:   PetscFunctionBegin;
10232:   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10235:   }

10237:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10238:   if (size == 1 || nsubcomm == 1) {
10239:     if (reuse == MAT_INITIAL_MATRIX) {
10240:       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10241:     } else {
10242:       PetscCheck(*matredundant != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10243:       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10244:     }
10245:     PetscFunctionReturn(PETSC_SUCCESS);
10246:   }

10248:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10249:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10250:   MatCheckPreallocated(mat, 1);

10252:   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10253:   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10254:     /* create psubcomm, then get subcomm */
10255:     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10256:     PetscCallMPI(MPI_Comm_size(comm, &size));
10257:     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);

10259:     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10260:     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10261:     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10262:     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10263:     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10264:     newsubcomm = PETSC_TRUE;
10265:     PetscCall(PetscSubcommDestroy(&psubcomm));
10266:   }

10268:   /* get isrow, iscol and a local sequential matrix matseq[0] */
10269:   if (reuse == MAT_INITIAL_MATRIX) {
10270:     mloc_sub = PETSC_DECIDE;
10271:     nloc_sub = PETSC_DECIDE;
10272:     if (bs < 1) {
10273:       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10274:       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10275:     } else {
10276:       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10277:       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10278:     }
10279:     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10280:     rstart = rend - mloc_sub;
10281:     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10282:     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10283:   } else { /* reuse == MAT_REUSE_MATRIX */
10284:     PetscCheck(*matredundant != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10285:     /* retrieve subcomm */
10286:     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10287:     redund = (*matredundant)->redundant;
10288:     isrow  = redund->isrow;
10289:     iscol  = redund->iscol;
10290:     matseq = redund->matseq;
10291:   }
10292:   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));

10294:   /* get matredundant over subcomm */
10295:   if (reuse == MAT_INITIAL_MATRIX) {
10296:     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));

10298:     /* create a supporting struct and attach it to C for reuse */
10299:     PetscCall(PetscNew(&redund));
10300:     (*matredundant)->redundant = redund;
10301:     redund->isrow              = isrow;
10302:     redund->iscol              = iscol;
10303:     redund->matseq             = matseq;
10304:     if (newsubcomm) {
10305:       redund->subcomm = subcomm;
10306:     } else {
10307:       redund->subcomm = MPI_COMM_NULL;
10308:     }
10309:   } else {
10310:     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10311:   }
10312: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10313:   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10314:     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10315:     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10316:   }
10317: #endif
10318:   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10319:   PetscFunctionReturn(PETSC_SUCCESS);
10320: }

10322: /*@C
10323:    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10324:    a given `Mat`. Each submatrix can span multiple procs.

10326:    Collective

10328:    Input Parameters:
10329: +  mat - the matrix
10330: .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10331: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

10333:    Output Parameter:
10334: .  subMat - parallel sub-matrices each spanning a given `subcomm`

10336:   Level: advanced

10338:   Notes:
10339:   The submatrix partition across processors is dictated by `subComm` a
10340:   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10341:   is not restricted to be grouped with consecutive original ranks.

10343:   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10344:   map directly to the layout of the original matrix [wrt the local
10345:   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10346:   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10347:   the `subMat`. However the offDiagMat looses some columns - and this is
10348:   reconstructed with `MatSetValues()`

10350:   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks

10352: .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10353: @*/
10354: PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10355: {
10356:   PetscMPIInt commsize, subCommSize;

10358:   PetscFunctionBegin;
10359:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10360:   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10361:   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);

10363:   PetscCheck(scall != MAT_REUSE_MATRIX || *subMat != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10364:   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10365:   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10366:   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10367:   PetscFunctionReturn(PETSC_SUCCESS);
10368: }

10370: /*@
10371:    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering

10373:    Not Collective

10375:    Input Parameters:
10376: +  mat - matrix to extract local submatrix from
10377: .  isrow - local row indices for submatrix
10378: -  iscol - local column indices for submatrix

10380:    Output Parameter:
10381: .  submat - the submatrix

10383:    Level: intermediate

10385:    Notes:
10386:    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.

10388:    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10389:    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.

10391:    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10392:    `MatSetValuesBlockedLocal()` will also be implemented.

10394:    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10395:    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.

10397: .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10398: @*/
10399: PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10400: {
10401:   PetscFunctionBegin;
10405:   PetscCheckSameComm(isrow, 2, iscol, 3);
10407:   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");

10409:   if (mat->ops->getlocalsubmatrix) {
10410:     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10411:   } else {
10412:     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10413:   }
10414:   PetscFunctionReturn(PETSC_SUCCESS);
10415: }

10417: /*@
10418:    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`

10420:    Not Collective

10422:    Input Parameters:
10423: +  mat - matrix to extract local submatrix from
10424: .  isrow - local row indices for submatrix
10425: .  iscol - local column indices for submatrix
10426: -  submat - the submatrix

10428:    Level: intermediate

10430: .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()`
10431: @*/
10432: PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10433: {
10434:   PetscFunctionBegin;
10438:   PetscCheckSameComm(isrow, 2, iscol, 3);

10442:   if (mat->ops->restorelocalsubmatrix) {
10443:     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10444:   } else {
10445:     PetscCall(MatDestroy(submat));
10446:   }
10447:   *submat = NULL;
10448:   PetscFunctionReturn(PETSC_SUCCESS);
10449: }

10451: /*@
10452:    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix

10454:    Collective

10456:    Input Parameter:
10457: .  mat - the matrix

10459:    Output Parameter:
10460: .  is - if any rows have zero diagonals this contains the list of them

10462:    Level: developer

10464: .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10465: @*/
10466: PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10467: {
10468:   PetscFunctionBegin;
10471:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10472:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");

10474:   if (!mat->ops->findzerodiagonals) {
10475:     Vec                diag;
10476:     const PetscScalar *a;
10477:     PetscInt          *rows;
10478:     PetscInt           rStart, rEnd, r, nrow = 0;

10480:     PetscCall(MatCreateVecs(mat, &diag, NULL));
10481:     PetscCall(MatGetDiagonal(mat, diag));
10482:     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10483:     PetscCall(VecGetArrayRead(diag, &a));
10484:     for (r = 0; r < rEnd - rStart; ++r)
10485:       if (a[r] == 0.0) ++nrow;
10486:     PetscCall(PetscMalloc1(nrow, &rows));
10487:     nrow = 0;
10488:     for (r = 0; r < rEnd - rStart; ++r)
10489:       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10490:     PetscCall(VecRestoreArrayRead(diag, &a));
10491:     PetscCall(VecDestroy(&diag));
10492:     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10493:   } else {
10494:     PetscUseTypeMethod(mat, findzerodiagonals, is);
10495:   }
10496:   PetscFunctionReturn(PETSC_SUCCESS);
10497: }

10499: /*@
10500:    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)

10502:    Collective

10504:    Input Parameter:
10505: .  mat - the matrix

10507:    Output Parameter:
10508: .  is - contains the list of rows with off block diagonal entries

10510:    Level: developer

10512: .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10513: @*/
10514: PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10515: {
10516:   PetscFunctionBegin;
10519:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10520:   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");

10522:   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10523:   PetscFunctionReturn(PETSC_SUCCESS);
10524: }

10526: /*@C
10527:   MatInvertBlockDiagonal - Inverts the block diagonal entries.

10529:   Collective; No Fortran Support

10531:   Input Parameters:
10532: . mat - the matrix

10534:   Output Parameters:
10535: . values - the block inverses in column major order (FORTRAN-like)

10537:   Level: advanced

10539:    Notes:
10540:    The size of the blocks is determined by the block size of the matrix.

10542:    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case

10544:    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size

10546: .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10547: @*/
10548: PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10549: {
10550:   PetscFunctionBegin;
10552:   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10553:   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10554:   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10555:   PetscFunctionReturn(PETSC_SUCCESS);
10556: }

10558: /*@C
10559:   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.

10561:   Collective; No Fortran Support

10563:   Input Parameters:
10564: + mat - the matrix
10565: . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10566: - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`

10568:   Output Parameters:
10569: . values - the block inverses in column major order (FORTRAN-like)

10571:   Level: advanced

10573:   Notes:
10574:   Use `MatInvertBlockDiagonal()` if all blocks have the same size

10576:   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case

10578: .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10579: @*/
10580: PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10581: {
10582:   PetscFunctionBegin;
10584:   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10585:   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10586:   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10587:   PetscFunctionReturn(PETSC_SUCCESS);
10588: }

10590: /*@
10591:   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A

10593:   Collective

10595:   Input Parameters:
10596: + A - the matrix
10597: - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.

10599:   Level: advanced

10601:   Note:
10602:   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`

10604: .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`
10605: @*/
10606: PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10607: {
10608:   const PetscScalar *vals;
10609:   PetscInt          *dnnz;
10610:   PetscInt           m, rstart, rend, bs, i, j;

10612:   PetscFunctionBegin;
10613:   PetscCall(MatInvertBlockDiagonal(A, &vals));
10614:   PetscCall(MatGetBlockSize(A, &bs));
10615:   PetscCall(MatGetLocalSize(A, &m, NULL));
10616:   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10617:   PetscCall(PetscMalloc1(m / bs, &dnnz));
10618:   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10619:   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10620:   PetscCall(PetscFree(dnnz));
10621:   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10622:   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10623:   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10624:   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10625:   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10626:   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10627:   PetscFunctionReturn(PETSC_SUCCESS);
10628: }

10630: /*@C
10631:     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10632:     via `MatTransposeColoringCreate()`.

10634:     Collective

10636:     Input Parameter:
10637: .   c - coloring context

10639:     Level: intermediate

10641: .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`
10642: @*/
10643: PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10644: {
10645:   MatTransposeColoring matcolor = *c;

10647:   PetscFunctionBegin;
10648:   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10649:   if (--((PetscObject)matcolor)->refct > 0) {
10650:     matcolor = NULL;
10651:     PetscFunctionReturn(PETSC_SUCCESS);
10652:   }

10654:   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10655:   PetscCall(PetscFree(matcolor->rows));
10656:   PetscCall(PetscFree(matcolor->den2sp));
10657:   PetscCall(PetscFree(matcolor->colorforcol));
10658:   PetscCall(PetscFree(matcolor->columns));
10659:   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10660:   PetscCall(PetscHeaderDestroy(c));
10661:   PetscFunctionReturn(PETSC_SUCCESS);
10662: }

10664: /*@C
10665:     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10666:     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10667:     `MatTransposeColoring` to sparse B.

10669:     Collective

10671:     Input Parameters:
10672: +   B - sparse matrix B
10673: .   Btdense - symbolic dense matrix B^T
10674: -   coloring - coloring context created with `MatTransposeColoringCreate()`

10676:     Output Parameter:
10677: .   Btdense - dense matrix B^T

10679:     Level: developer

10681:     Note:
10682:     These are used internally for some implementations of `MatRARt()`

10684: .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10685: @*/
10686: PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10687: {
10688:   PetscFunctionBegin;

10693:   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10694:   PetscFunctionReturn(PETSC_SUCCESS);
10695: }

10697: /*@C
10698:     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10699:     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10700:     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10701:     Csp from Cden.

10703:     Collective

10705:     Input Parameters:
10706: +   coloring - coloring context created with `MatTransposeColoringCreate()`
10707: -   Cden - matrix product of a sparse matrix and a dense matrix Btdense

10709:     Output Parameter:
10710: .   Csp - sparse matrix

10712:     Level: developer

10714:     Note:
10715:     These are used internally for some implementations of `MatRARt()`

10717: .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10718: @*/
10719: PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10720: {
10721:   PetscFunctionBegin;

10726:   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10727:   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10728:   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10729:   PetscFunctionReturn(PETSC_SUCCESS);
10730: }

10732: /*@C
10733:    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.

10735:    Collective

10737:    Input Parameters:
10738: +  mat - the matrix product C
10739: -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`

10741:     Output Parameter:
10742: .   color - the new coloring context

10744:     Level: intermediate

10746: .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10747:           `MatTransColoringApplyDenToSp()`
10748: @*/
10749: PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10750: {
10751:   MatTransposeColoring c;
10752:   MPI_Comm             comm;

10754:   PetscFunctionBegin;
10755:   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10756:   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10757:   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));

10759:   c->ctype = iscoloring->ctype;
10760:   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);

10762:   *color = c;
10763:   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10764:   PetscFunctionReturn(PETSC_SUCCESS);
10765: }

10767: /*@
10768:       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10769:         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10770:         same, otherwise it will be larger

10772:      Not Collective

10774:   Input Parameter:
10775: .    A  - the matrix

10777:   Output Parameter:
10778: .    state - the current state

10780:   Level: intermediate

10782:   Notes:
10783:     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10784:          different matrices

10786:     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix

10788:     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.

10790: .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10791: @*/
10792: PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10793: {
10794:   PetscFunctionBegin;
10796:   *state = mat->nonzerostate;
10797:   PetscFunctionReturn(PETSC_SUCCESS);
10798: }

10800: /*@
10801:       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10802:                  matrices from each processor

10804:     Collective

10806:    Input Parameters:
10807: +    comm - the communicators the parallel matrix will live on
10808: .    seqmat - the input sequential matrices
10809: .    n - number of local columns (or `PETSC_DECIDE`)
10810: -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

10812:    Output Parameter:
10813: .    mpimat - the parallel matrix generated

10815:     Level: developer

10817:    Note:
10818:     The number of columns of the matrix in EACH processor MUST be the same.

10820: .seealso: [](chapter_matrices), `Mat`
10821: @*/
10822: PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10823: {
10824:   PetscMPIInt size;

10826:   PetscFunctionBegin;
10827:   PetscCallMPI(MPI_Comm_size(comm, &size));
10828:   if (size == 1) {
10829:     if (reuse == MAT_INITIAL_MATRIX) {
10830:       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10831:     } else {
10832:       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10833:     }
10834:     PetscFunctionReturn(PETSC_SUCCESS);
10835:   }

10837:   PetscCheck(reuse != MAT_REUSE_MATRIX || seqmat != *mpimat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");

10839:   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10840:   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10841:   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10842:   PetscFunctionReturn(PETSC_SUCCESS);
10843: }

10845: /*@
10846:      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.

10848:     Collective

10850:    Input Parameters:
10851: +    A   - the matrix to create subdomains from
10852: -    N   - requested number of subdomains

10854:    Output Parameters:
10855: +    n   - number of subdomains resulting on this rank
10856: -    iss - `IS` list with indices of subdomains on this rank

10858:     Level: advanced

10860:     Note:
10861:     The number of subdomains must be smaller than the communicator size

10863: .seealso: [](chapter_matrices), `Mat`, `IS`
10864: @*/
10865: PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10866: {
10867:   MPI_Comm    comm, subcomm;
10868:   PetscMPIInt size, rank, color;
10869:   PetscInt    rstart, rend, k;

10871:   PetscFunctionBegin;
10872:   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10873:   PetscCallMPI(MPI_Comm_size(comm, &size));
10874:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10875:   PetscCheck(N >= 1 && N < (PetscInt)size, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subdomains must be > 0 and < %d, got N = %" PetscInt_FMT, size, N);
10876:   *n    = 1;
10877:   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10878:   color = rank / k;
10879:   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10880:   PetscCall(PetscMalloc1(1, iss));
10881:   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10882:   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10883:   PetscCallMPI(MPI_Comm_free(&subcomm));
10884:   PetscFunctionReturn(PETSC_SUCCESS);
10885: }

10887: /*@
10888:    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.

10890:    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10891:    If they are not the same, uses `MatMatMatMult()`.

10893:    Once the coarse grid problem is constructed, correct for interpolation operators
10894:    that are not of full rank, which can legitimately happen in the case of non-nested
10895:    geometric multigrid.

10897:    Input Parameters:
10898: +  restrct - restriction operator
10899: .  dA - fine grid matrix
10900: .  interpolate - interpolation operator
10901: .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10902: -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate

10904:    Output Parameters:
10905: .  A - the Galerkin coarse matrix

10907:    Options Database Key:
10908: .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used

10910:    Level: developer

10912: .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10913: @*/
10914: PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10915: {
10916:   IS  zerorows;
10917:   Vec diag;

10919:   PetscFunctionBegin;
10920:   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10921:   /* Construct the coarse grid matrix */
10922:   if (interpolate == restrct) {
10923:     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10924:   } else {
10925:     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10926:   }

10928:   /* If the interpolation matrix is not of full rank, A will have zero rows.
10929:      This can legitimately happen in the case of non-nested geometric multigrid.
10930:      In that event, we set the rows of the matrix to the rows of the identity,
10931:      ignoring the equations (as the RHS will also be zero). */

10933:   PetscCall(MatFindZeroRows(*A, &zerorows));

10935:   if (zerorows != NULL) { /* if there are any zero rows */
10936:     PetscCall(MatCreateVecs(*A, &diag, NULL));
10937:     PetscCall(MatGetDiagonal(*A, diag));
10938:     PetscCall(VecISSet(diag, zerorows, 1.0));
10939:     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10940:     PetscCall(VecDestroy(&diag));
10941:     PetscCall(ISDestroy(&zerorows));
10942:   }
10943:   PetscFunctionReturn(PETSC_SUCCESS);
10944: }

10946: /*@C
10947:     MatSetOperation - Allows user to set a matrix operation for any matrix type

10949:    Logically Collective

10951:     Input Parameters:
10952: +   mat - the matrix
10953: .   op - the name of the operation
10954: -   f - the function that provides the operation

10956:    Level: developer

10958:     Usage:
10959: .vb
10960:   extern PetscErrorCode usermult(Mat, Vec, Vec);

10962:   PetscCall(MatCreateXXX(comm, ..., &A));
10963:   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10964: .ve

10966:     Notes:
10967:     See the file `include/petscmat.h` for a complete list of matrix
10968:     operations, which all have the form MATOP_<OPERATION>, where
10969:     <OPERATION> is the name (in all capital letters) of the
10970:     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).

10972:     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10973:     sequence as the usual matrix interface routines, since they
10974:     are intended to be accessed via the usual matrix interface
10975:     routines, e.g.,
10976: .vb
10977:   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10978: .ve

10980:     In particular each function MUST return `PETSC_SUCCESS` on success and
10981:     nonzero on failure.

10983:     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.

10985: .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10986: @*/
10987: PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10988: {
10989:   PetscFunctionBegin;
10991:   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10992:   (((void (**)(void))mat->ops)[op]) = f;
10993:   PetscFunctionReturn(PETSC_SUCCESS);
10994: }

10996: /*@C
10997:     MatGetOperation - Gets a matrix operation for any matrix type.

10999:     Not Collective

11001:     Input Parameters:
11002: +   mat - the matrix
11003: -   op - the name of the operation

11005:     Output Parameter:
11006: .   f - the function that provides the operation

11008:     Level: developer

11010:     Usage:
11011: $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
11012: $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);

11014:     Notes:
11015:     See the file include/petscmat.h for a complete list of matrix
11016:     operations, which all have the form MATOP_<OPERATION>, where
11017:     <OPERATION> is the name (in all capital letters) of the
11018:     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).

11020:     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.

11022: .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11023: @*/
11024: PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11025: {
11026:   PetscFunctionBegin;
11028:   *f = (((void (**)(void))mat->ops)[op]);
11029:   PetscFunctionReturn(PETSC_SUCCESS);
11030: }

11032: /*@
11033:     MatHasOperation - Determines whether the given matrix supports the particular operation.

11035:    Not Collective

11037:    Input Parameters:
11038: +  mat - the matrix
11039: -  op - the operation, for example, `MATOP_GET_DIAGONAL`

11041:    Output Parameter:
11042: .  has - either `PETSC_TRUE` or `PETSC_FALSE`

11044:    Level: advanced

11046:    Note:
11047:    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.

11049: .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11050: @*/
11051: PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11052: {
11053:   PetscFunctionBegin;
11056:   if (mat->ops->hasoperation) {
11057:     PetscUseTypeMethod(mat, hasoperation, op, has);
11058:   } else {
11059:     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11060:     else {
11061:       *has = PETSC_FALSE;
11062:       if (op == MATOP_CREATE_SUBMATRIX) {
11063:         PetscMPIInt size;

11065:         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11066:         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11067:       }
11068:     }
11069:   }
11070:   PetscFunctionReturn(PETSC_SUCCESS);
11071: }

11073: /*@
11074:     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent

11076:    Collective

11078:    Input Parameters:
11079: .  mat - the matrix

11081:    Output Parameter:
11082: .  cong - either `PETSC_TRUE` or `PETSC_FALSE`

11084:    Level: beginner

11086: .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11087: @*/
11088: PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11089: {
11090:   PetscFunctionBegin;
11094:   if (!mat->rmap || !mat->cmap) {
11095:     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11096:     PetscFunctionReturn(PETSC_SUCCESS);
11097:   }
11098:   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11099:     PetscCall(PetscLayoutSetUp(mat->rmap));
11100:     PetscCall(PetscLayoutSetUp(mat->cmap));
11101:     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11102:     if (*cong) mat->congruentlayouts = 1;
11103:     else mat->congruentlayouts = 0;
11104:   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11105:   PetscFunctionReturn(PETSC_SUCCESS);
11106: }

11108: PetscErrorCode MatSetInf(Mat A)
11109: {
11110:   PetscFunctionBegin;
11111:   PetscUseTypeMethod(A, setinf);
11112:   PetscFunctionReturn(PETSC_SUCCESS);
11113: }

11115: /*@C
11116:    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
11117:    and possibly removes small values from the graph structure.

11119:    Collective

11121:    Input Parameters:
11122: +  A - the matrix
11123: .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11124: .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11125: -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value

11127:    Output Parameter:
11128: .  graph - the resulting graph

11130:    Level: advanced

11132: .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11133: @*/
11134: PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11135: {
11136:   PetscFunctionBegin;
11141:   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11142:   PetscFunctionReturn(PETSC_SUCCESS);
11143: }

11145: /*@
11146:   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11147:   meaning the same memory is used for the matrix, and no new memory is allocated.

11149:   Collective

11151:   Input Parameter:
11152: . A - the matrix

11154:   Output Parameter:
11155: . A - the matrix

11157:   Level: intermediate

11159: .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11160: @*/
11161: PetscErrorCode MatEliminateZeros(Mat A)
11162: {
11163:   PetscFunctionBegin;
11165:   PetscUseTypeMethod(A, eliminatezeros);
11166:   PetscFunctionReturn(PETSC_SUCCESS);
11167: }