Actual source code: matrix.c

  1: /*
  2:    This is where the abstract matrix operations are defined
  3: */

  5: #include <petsc/private/matimpl.h>
  6: #include <petsc/private/isimpl.h>
  7: #include <petsc/private/vecimpl.h>

  9: /* Logging support */
 10: PetscClassId MAT_CLASSID;
 11: PetscClassId MAT_COLORING_CLASSID;
 12: PetscClassId MAT_FDCOLORING_CLASSID;
 13: PetscClassId MAT_TRANSPOSECOLORING_CLASSID;

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

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

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

 51:    Logically Collective on mat

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

 58:    Output Parameter:
 59: .  x  - the matrix

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

 68:    Level: intermediate

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

 79:   MatCheckPreallocated(x, 1);

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

 93:   MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY);
 94:   MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY);
 95:   PetscRandomDestroy(&randObj);
 96:   return 0;
 97: }

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

102:    Logically Collective on mat

104:    Input Parameter:
105: .  mat - the factored matrix

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

112:    Level: advanced

114:    Notes:
115:     This routine does not work for factorizations done with external packages.

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

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

121: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
122:           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
123: @*/
124: PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
125: {
129:   *pivot = mat->factorerror_zeropivot_value;
130:   *row   = mat->factorerror_zeropivot_row;
131:   return 0;
132: }

134: /*@
135:    MatFactorGetError - gets the error code from a factorization

137:    Logically Collective on mat

139:    Input Parameters:
140: .  mat - the factored matrix

142:    Output Parameter:
143: .  err  - the error code

145:    Level: advanced

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

150: .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
151:           `MatFactorError`
152: @*/
153: PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
154: {
157:   *err = mat->factorerrortype;
158:   return 0;
159: }

161: /*@
162:    MatFactorClearError - clears the error code in a factorization

164:    Logically Collective on mat

166:    Input Parameter:
167: .  mat - the factored matrix

169:    Level: developer

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

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

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

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

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

243:   Input Parameter:
244: .    A  - the matrix

246:   Output Parameter:
247: .    keptrows - the rows that are not completely zero

249:   Note:
250:     keptrows is set to NULL if all rows are nonzero.

252:   Level: intermediate

254: .seealso: `Mat`, `MatFindZeroRows()`
255:  @*/
256: PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
257: {
263:   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
264:   else MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows);
265:   return 0;
266: }

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

271:   Input Parameter:
272: .    A  - the matrix

274:   Output Parameter:
275: .    zerorows - the rows that are completely zero

277:   Note:
278:     zerorows is set to NULL if no rows are zero.

280:   Level: intermediate

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

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

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

309:    Not Collective

311:    Input Parameters:
312: .   A - the matrix

314:    Output Parameters:
315: .   a - the diagonal part (which is a SEQUENTIAL matrix)

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

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

322:    Level: advanced

324: .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
325: @*/
326: PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
327: {
332:   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
333:   else {
334:     PetscMPIInt size;

336:     MPI_Comm_size(PetscObjectComm((PetscObject)A), &size);
338:     *a = A;
339:   }
340:   return 0;
341: }

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

346:    Collective on mat

348:    Input Parameters:
349: .  mat - the matrix

351:    Output Parameter:
352: .   trace - the sum of the diagonal entries

354:    Level: advanced

356: .seealso: `Mat`
357: @*/
358: PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
359: {
360:   Vec diag;

364:   MatCreateVecs(mat, &diag, NULL);
365:   MatGetDiagonal(mat, diag);
366:   VecSum(diag, trace);
367:   VecDestroy(&diag);
368:   return 0;
369: }

371: /*@
372:    MatRealPart - Zeros out the imaginary part of the matrix

374:    Logically Collective on mat

376:    Input Parameters:
377: .  mat - the matrix

379:    Level: advanced

381: .seealso: `MatImaginaryPart()`
382: @*/
383: PetscErrorCode MatRealPart(Mat mat)
384: {
389:   MatCheckPreallocated(mat, 1);
390:   PetscUseTypeMethod(mat, realpart);
391:   return 0;
392: }

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

397:    Collective on mat

399:    Input Parameter:
400: .  mat - the matrix

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

406:    Note:
407:     the nghosts and ghosts are suitable to pass into `VecCreateGhost()`

409:    Level: advanced

411: .seealso: `Mat`, `VecCreateGhost()`
412: @*/
413: PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
414: {
419:   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
420:   else {
421:     if (nghosts) *nghosts = 0;
422:     if (ghosts) *ghosts = NULL;
423:   }
424:   return 0;
425: }

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

430:    Logically Collective on mat

432:    Input Parameters:
433: .  mat - the matrix

435:    Level: advanced

437: .seealso: `MatRealPart()`
438: @*/
439: PetscErrorCode MatImaginaryPart(Mat mat)
440: {
445:   MatCheckPreallocated(mat, 1);
446:   PetscUseTypeMethod(mat, imaginarypart);
447:   return 0;
448: }

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

453:    Not Collective

455:    Input Parameter:
456: .  mat - the matrix

458:    Output Parameters:
459: +  missing - is any diagonal missing
460: -  dd - first diagonal entry that is missing (optional) on this process

462:    Level: advanced

464: .seealso: `Mat`
465: @*/
466: PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
467: {
473:   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
474:   return 0;
475: }

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

482:    Not Collective

484:    Input Parameters:
485: +  mat - the matrix
486: -  row - the row to get

488:    Output Parameters:
489: +  ncols -  if not NULL, the number of nonzeros in the row
490: .  cols - if not NULL, the column numbers
491: -  vals - if not NULL, the values

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

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

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

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

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

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

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

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

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

535:    Level: advanced

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

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

556: /*@
557:    MatConjugate - replaces the matrix values with their complex conjugates

559:    Logically Collective on mat

561:    Input Parameters:
562: .  mat - the matrix

564:    Level: advanced

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

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

582:    Not Collective

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

590:    Notes:
591:    This routine should be called after you have finished examining the entries.

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

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

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

612:    Level: advanced

614: .seealso: `MatGetRow()`
615: @*/
616: PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
617: {
621:   if (!mat->ops->restorerow) return 0;
622:   (*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
623:   if (ncols) *ncols = 0;
624:   if (cols) *cols = NULL;
625:   if (vals) *vals = NULL;
626:   return 0;
627: }

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

633:    Not Collective

635:    Input Parameters:
636: .  mat - the matrix

638:    Note:
639:    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.

641:    Level: advanced

643: .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
644: @*/
645: PetscErrorCode MatGetRowUpperTriangular(Mat mat)
646: {
651:   MatCheckPreallocated(mat, 1);
652:   if (!mat->ops->getrowuppertriangular) return 0;
653:   PetscUseTypeMethod(mat, getrowuppertriangular);
654:   return 0;
655: }

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

660:    Not Collective

662:    Input Parameters:
663: .  mat - the matrix

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

668:    Level: advanced

670: .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()`
671: @*/
672: PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
673: {
678:   MatCheckPreallocated(mat, 1);
679:   if (!mat->ops->restorerowuppertriangular) return 0;
680:   PetscUseTypeMethod(mat, restorerowuppertriangular);
681:   return 0;
682: }

684: /*@C
685:    MatSetOptionsPrefix - Sets the prefix used for searching for all
686:    `Mat` options in the database.

688:    Logically Collective on A

690:    Input Parameters:
691: +  A - the matrix
692: -  prefix - the prefix to prepend to all option names

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

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

702:    Level: advanced

704: .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
705: @*/
706: PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
707: {
709:   PetscObjectSetOptionsPrefix((PetscObject)A, prefix);
710:   return 0;
711: }

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

717:    Logically Collective on A

719:    Input Parameters:
720: +  A - the matrix
721: -  prefix - the prefix to prepend to all option names for the factored matrix

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:    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
728:    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`

730:    Level: developer

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

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

752:    Logically Collective on A

754:    Input Parameters:
755: +  A - the matrix
756: -  prefix - the prefix to prepend to all option names for the factored matrix

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

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

765:    Level: developer

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

777:   if (!prefix) return 0;
778:   if (!buf) {
779:     MatSetOptionsPrefixFactor(A, prefix);
780:     return 0;
781:   }

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

793: /*@C
794:    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
795:    matrix options in the database.

797:    Logically Collective on A

799:    Input Parameters:
800: +  A - the matrix
801: -  prefix - the prefix to prepend to all option names

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

807:    Level: advanced

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

818: /*@C
819:    MatGetOptionsPrefix - Gets the prefix used for searching for all
820:    matrix options in the database.

822:    Not Collective

824:    Input Parameter:
825: .  A - the matrix

827:    Output Parameter:
828: .  prefix - pointer to the prefix string used

830:    Fortran Note:
831:     On the fortran side, the user should pass in a string 'prefix' of
832:    sufficient length to hold the prefix.

834:    Level: advanced

836: .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
837: @*/
838: PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
839: {
842:   PetscObjectGetOptionsPrefix((PetscObject)A, prefix);
843:   return 0;
844: }

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

849:    Collective on A

851:    Input Parameters:
852: .  A - the matrix

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

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

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

861:    Level: beginner

863: .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
864: @*/
865: PetscErrorCode MatResetPreallocation(Mat A)
866: {
869:   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
870:   return 0;
871: }

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

876:    Collective on A

878:    Input Parameters:
879: .  A - the matrix

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

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

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

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

890:    Level: intermediate

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

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

913: #if defined(PETSC_HAVE_SAWS)
914: #include <petscviewersaws.h>
915: #endif

917: /*@C
918:    MatViewFromOptions - View properties of the matrix from the options database

920:    Collective on A

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

927:   Options Database:
928: .  -mat_view [viewertype]:... - the viewer and its options

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

942:    Level: intermediate

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

953: /*@C
954:    MatView - display information about a matrix in a variety ways

956:    Collective on mat

958:    Input Parameters:
959: +  mat - the matrix
960: -  viewer - visualization context

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

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

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

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

1008:    Level: beginner

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1141:    Collective on mat

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

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

1153:    Level: beginner

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

1272:   PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0);
1273:   PetscUseTypeMethod(mat, load, viewer);
1274:   PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0);
1275:   return 0;
1276: }

1278: static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1279: {
1280:   Mat_Redundant *redund = *redundant;

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

1298:     if (redund->subcomm) PetscCommDestroy(&redund->subcomm);
1299:     PetscFree(redund);
1300:   }
1301:   return 0;
1302: }

1304: /*@C
1305:    MatDestroy - Frees space taken by a matrix.

1307:    Collective on A

1309:    Input Parameter:
1310: .  A - the matrix

1312:    Level: beginner

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

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

1331:   /* if memory was published with SAWs then destroy it */
1332:   PetscObjectSAWsViewOff((PetscObject)*A);
1333:   PetscTryTypeMethod((*A), destroy);

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

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

1359:    Not Collective

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

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

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

1374:    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1375:    options cannot be mixed without intervening calls to the assembly
1376:    routines.

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

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

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

1390:    Level: beginner

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

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

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

1412:   if (PetscDefined(USE_DEBUG)) {
1413:     PetscInt i, j;

1416:     for (i = 0; i < m; i++) {
1417:       for (j = 0; j < n; j++) {
1418:         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1419: #if defined(PETSC_USE_COMPLEX)
1420:           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]);
1421: #else
1422:           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]);
1423: #endif
1424:       }
1425:     }
1428:   }

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

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

1445:    Not Collective

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

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

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

1460:    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1461:    options cannot be mixed without intervening calls to the assembly
1462:    routines.

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

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

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

1476:    Level: beginner

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

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

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

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

1504: /*@
1505:    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1506:         values into a matrix

1508:    Not Collective

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

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

1518:    All the nonzeros in the row must be provided

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

1522:    The row must belong to this process

1524:    Level: intermediate

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

1536:   ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow);
1537:   MatSetValuesRow(mat, globalrow, v);
1538:   return 0;
1539: }

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

1545:    Not Collective

1547:    Input Parameters:
1548: +  mat - the matrix
1549: .  row - the (block) row to set
1550: -  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

1552:    Notes:
1553:    The values, v, are column-oriented for the block version.

1555:    All the nonzeros in the row must be provided

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

1559:    The row must belong to this process

1561:    Level: advanced

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

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

1587: /*@
1588:    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1589:      Using structured grid indexing

1591:    Not Collective

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

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

1605:    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1606:    options cannot be mixed without intervening calls to the assembly
1607:    routines.

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

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

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

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

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

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

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

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

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

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

1649:    Level: beginner

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

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

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

1699: /*@
1700:    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1701:      Using structured grid indexing

1703:    Not Collective

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

1714:    Notes:
1715:    By default the values, v, are row-oriented and unsorted.
1716:    See `MatSetOption()` for other options.

1718:    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1719:    options cannot be mixed without intervening calls to the assembly
1720:    routines.

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

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

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

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

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

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

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

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

1754:    Level: beginner

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

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

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

1806: /*@
1807:    MatSetStencil - Sets the grid information for setting values into a matrix via
1808:         `MatSetValuesStencil()`

1810:    Not Collective

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

1819:    Notes:
1820:    Inspired by the structured grid interface to the HYPRE package
1821:    (www.llnl.gov/CASC/hyper)

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

1826:    Level: beginner

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

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

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

1851:    Not Collective

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

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

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

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

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

1876:    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1877:    options cannot be mixed without intervening calls to the assembly
1878:    routines.

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

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

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

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

1909:    Level: intermediate

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

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

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

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

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

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

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

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

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

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

2001:    Level: advanced

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

2017:   PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0);
2018:   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2019:   PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0);
2020:   return 0;
2021: }

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

2027:    Not Collective

2029:    Input Parameters:
2030: +  mat - the matrix
2031: .  nrow, irow - number of rows and their local indices
2032: -  ncol, icol - number of columns and their local indices

2034:    Output Parameter:
2035: .  y -  a logically two-dimensional array of values

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

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

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

2049:    Level: advanced

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

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

2095:   Not Collective

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

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

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

2109:   Level: advanced

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

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

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

2136:    Not Collective

2138:    Input Parameters:
2139: +  x - the matrix
2140: .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2141: -  cmapping - column mapping

2143:    Level: intermediate

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

2148: .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2149: @*/
2150: PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2151: {
2156:   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2157:   else {
2158:     PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping);
2159:     PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping);
2160:   }
2161:   return 0;
2162: }

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

2167:    Not Collective

2169:    Input Parameter:
2170: .  A - the matrix

2172:    Output Parameters:
2173: + rmapping - row mapping
2174: - cmapping - column mapping

2176:    Level: advanced

2178: .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2179: @*/
2180: PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2181: {
2184:   if (rmapping) {
2186:     *rmapping = A->rmap->mapping;
2187:   }
2188:   if (cmapping) {
2190:     *cmapping = A->cmap->mapping;
2191:   }
2192:   return 0;
2193: }

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

2198:    Logically Collective on A

2200:    Input Parameters:
2201: +  A - the matrix
2202: . rmap - row layout
2203: - cmap - column layout

2205:    Level: advanced

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

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

2220: /*@
2221:    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns

2223:    Not Collective

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

2228:    Output Parameters:
2229: + rmap - row layout
2230: - cmap - column layout

2232:    Level: advanced

2234: .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2235: @*/
2236: PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2237: {
2240:   if (rmap) {
2242:     *rmap = A->rmap;
2243:   }
2244:   if (cmap) {
2246:     *cmap = A->cmap;
2247:   }
2248:   return 0;
2249: }

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

2255:    Not Collective

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

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

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

2270:    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2271:    options cannot be mixed without intervening calls to the assembly
2272:    routines.

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

2277:    Level: intermediate

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

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

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

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

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

2340:    Not Collective

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

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

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

2356:    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2357:    options cannot be mixed without intervening calls to the assembly
2358:    routines.

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

2363:    Level: intermediate

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

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

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

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

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

2437:    Collective on mat

2439:    Input Parameters:
2440: +  mat - the matrix
2441: -  x   - the vector to be multiplied

2443:    Output Parameters:
2444: .  y - the result

2446:    Note:
2447:    The vectors x and y cannot be the same.  I.e., one cannot
2448:    call `MatMultDiagonalBlock`(A,y,y).

2450:    Level: developer

2452: .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2453: @*/
2454: PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2455: {

2464:   MatCheckPreallocated(mat, 1);

2466:   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2467:   PetscObjectStateIncrease((PetscObject)y);
2468:   return 0;
2469: }

2471: /* --------------------------------------------------------*/
2472: /*@
2473:    MatMult - Computes the matrix-vector product, y = Ax.

2475:    Neighbor-wise Collective on mat

2477:    Input Parameters:
2478: +  mat - the matrix
2479: -  x   - the vector to be multiplied

2481:    Output Parameters:
2482: .  y - the result

2484:    Note:
2485:    The vectors x and y cannot be the same.  I.e., one cannot
2486:    call `MatMult`(A,y,y).

2488:    Level: beginner

2490: .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2491: @*/
2492: PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2493: {
2505:   VecSetErrorIfLocked(y, 3);
2506:   if (mat->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
2507:   MatCheckPreallocated(mat, 1);

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

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

2521:    Neighbor-wise Collective on mat

2523:    Input Parameters:
2524: +  mat - the matrix
2525: -  x   - the vector to be multiplied

2527:    Output Parameters:
2528: .  y - the result

2530:    Notes:
2531:    The vectors x and y cannot be the same.  I.e., one cannot
2532:    call `MatMultTranspose`(A,y,y).

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

2537:    Level: beginner

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


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

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

2574: /*@
2575:    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.

2577:    Neighbor-wise Collective on mat

2579:    Input Parameters:
2580: +  mat - the matrix
2581: -  x   - the vector to be multilplied

2583:    Output Parameters:
2584: .  y - the result

2586:    Notes:
2587:    The vectors x and y cannot be the same.  I.e., one cannot
2588:    call `MatMultHermitianTranspose`(A,y,y).

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

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

2594:    Level: beginner

2596: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2597: @*/
2598: PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2599: {

2612:   MatCheckPreallocated(mat, 1);

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

2638: /*@
2639:     MatMultAdd -  Computes v3 = v2 + A * v1.

2641:     Neighbor-wise Collective on mat

2643:     Input Parameters:
2644: +   mat - the matrix
2645: -   v1, v2 - the vectors

2647:     Output Parameters:
2648: .   v3 - the result

2650:     Note:
2651:     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2652:     call `MatMultAdd`(A,v1,v2,v1).

2654:     Level: beginner

2656: .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2657: @*/
2658: PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2659: {

2674:   MatCheckPreallocated(mat, 1);

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

2685: /*@
2686:    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.

2688:    Neighbor-wise Collective on mat

2690:    Input Parameters:
2691: +  mat - the matrix
2692: -  v1, v2 - the vectors

2694:    Output Parameters:
2695: .  v3 - the result

2697:    Note:
2698:    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2699:    call `MatMultTransposeAdd`(A,v1,v2,v1).

2701:    Level: beginner

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


2722:   MatCheckPreallocated(mat, 1);

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

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

2736:    Neighbor-wise Collective on mat

2738:    Input Parameters:
2739: +  mat - the matrix
2740: -  v1, v2 - the vectors

2742:    Output Parameters:
2743: .  v3 - the result

2745:    Note:
2746:    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2747:    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).

2749:    Level: beginner

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

2767:   MatCheckPreallocated(mat, 1);

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

2794: /*@C
2795:    MatGetFactorType - gets the type of factorization it is

2797:    Not Collective

2799:    Input Parameters:
2800: .  mat - the matrix

2802:    Output Parameters:
2803: .  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`

2805:    Level: intermediate

2807: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2808:           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2809: @*/
2810: PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2811: {
2815:   *t = mat->factortype;
2816:   return 0;
2817: }

2819: /*@C
2820:    MatSetFactorType - sets the type of factorization it is

2822:    Logically Collective on mat

2824:    Input Parameters:
2825: +  mat - the matrix
2826: -  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`

2828:    Level: intermediate

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

2841: /* ------------------------------------------------------------*/
2842: /*@C
2843:    MatGetInfo - Returns information about matrix storage (number of
2844:    nonzeros, memory, etc.).

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

2848:    Input Parameter:
2849: .  mat - the matrix

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

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

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

2874:       MatGetInfo(A,MAT_LOCAL,&info);
2875:       mal  = info.mallocs;
2876:       nz_a = info.nz_allocated;
2877: .ve

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

2890:       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2891:       mal = info(MAT_INFO_MALLOCS)
2892:       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2893: .ve

2895:     Level: intermediate

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

2900: .seealso: `MatInfo`, `MatStashGetInfo()`
2901: @*/
2902: PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2903: {
2907:   MatCheckPreallocated(mat, 1);
2908:   PetscUseTypeMethod(mat, getinfo, flag, info);
2909:   return 0;
2910: }

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

2922: /* ----------------------------------------------------------*/

2924: /*@C
2925:    MatLUFactor - Performs in-place LU factorization of matrix.

2927:    Collective on mat

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

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

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

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

2949:    Level: developer

2951:    Developer Note:
2952:    The Fortran interface is not autogenerated as the f90
2953:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

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

2969:   MatCheckPreallocated(mat, 1);
2970:   if (!info) {
2971:     MatFactorInfoInitialize(&tinfo);
2972:     info = &tinfo;
2973:   }

2975:   PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0);
2976:   PetscUseTypeMethod(mat, lufactor, row, col, info);
2977:   PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0);
2978:   PetscObjectStateIncrease((PetscObject)mat);
2979:   return 0;
2980: }

2982: /*@C
2983:    MatILUFactor - Performs in-place ILU factorization of matrix.

2985:    Collective on mat

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

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

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

3006:    Level: developer

3008:    Developer Note:
3009:    The Fortran interface is not autogenerated as the f90
3010:    interface definition cannot be generated correctly [due to MatFactorInfo]

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

3026:   PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0);
3027:   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3028:   PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0);
3029:   PetscObjectStateIncrease((PetscObject)mat);
3030:   return 0;
3031: }

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

3037:    Collective on fact

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

3049:    Notes:
3050:     See [Matrix Factorization](sec_matfactor) for additional information about factorizations

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

3056:    Level: developer

3058:    Developer Note:
3059:    The Fortran interface is not autogenerated as the f90
3060:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

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

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

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

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

3098:    Collective on fact

3100:    Input Parameters:
3101: +  fact - the factor matrix obtained with `MatGetFactor()`
3102: .  mat - the matrix
3103: -  info - options for factorization

3105:    Notes:
3106:    See `MatLUFactor()` for in-place factorization.  See
3107:    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.

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

3113:    Level: developer

3115:     Developer Note:
3116:     The Fortran interface is not autogenerated as the f90
3117:     interface definition cannot be generated correctly [due to `MatFactorInfo`]

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

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

3134:   MatCheckPreallocated(mat, 2);
3135:   if (!info) {
3136:     MatFactorInfoInitialize(&tinfo);
3137:     info = &tinfo;
3138:   }

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

3150: /*@C
3151:    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3152:    symmetric matrix.

3154:    Collective on mat

3156:    Input Parameters:
3157: +  mat - the matrix
3158: .  perm - row and column permutations
3159: -  f - expected fill as ratio of original fill

3161:    Notes:
3162:    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3163:    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.

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

3169:    Level: developer

3171:    Developer Note:
3172:    The Fortran interface is not autogenerated as the f90
3173:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

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

3189:   MatCheckPreallocated(mat, 1);
3190:   if (!info) {
3191:     MatFactorInfoInitialize(&tinfo);
3192:     info = &tinfo;
3193:   }

3195:   PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0);
3196:   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3197:   PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0);
3198:   PetscObjectStateIncrease((PetscObject)mat);
3199:   return 0;
3200: }

3202: /*@C
3203:    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3204:    of a symmetric matrix.

3206:    Collective on fact

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

3217:    Notes:
3218:    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3219:    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.

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

3225:    Level: developer

3227:    Developer Note:
3228:    The Fortran interface is not autogenerated as the f90
3229:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

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

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

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

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

3269:    Collective on fact

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

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

3282:    Level: developer

3284:    Developer Note:
3285:    The Fortran interface is not autogenerated as the f90
3286:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

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

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

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

3318: /*@
3319:    MatQRFactor - Performs in-place QR factorization of matrix.

3321:    Collective on mat

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

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

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

3339:    Level: developer

3341:    Developer Note:
3342:    The Fortran interface is not autogenerated as the f90
3343:    interface definition cannot be generated correctly [due to MatFactorInfo]

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

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

3368:    Collective on fact

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

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

3383:    Level: developer

3385:    Developer Note:
3386:    The Fortran interface is not autogenerated as the f90
3387:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

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

3402:   MatCheckPreallocated(mat, 2);
3403:   if (!info) {
3404:     MatFactorInfoInitialize(&tinfo);
3405:     info = &tinfo;
3406:   }

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

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

3419:    Collective on fact

3421:    Input Parameters:
3422: +  fact - the factor matrix obtained with `MatGetFactor()`
3423: .  mat - the matrix
3424: -  info - options for factorization

3426:    Notes:
3427:    See `MatQRFactor()` for in-place factorization.

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

3433:    Level: developer

3435:    Developer Note:
3436:    The Fortran interface is not autogenerated as the f90
3437:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

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

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

3453:   MatCheckPreallocated(mat, 2);
3454:   if (!info) {
3455:     MatFactorInfoInitialize(&tinfo);
3456:     info = &tinfo;
3457:   }

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

3469: /* ----------------------------------------------------------------*/
3470: /*@
3471:    MatSolve - Solves A x = b, given a factored matrix.

3473:    Neighbor-wise Collective on mat

3475:    Input Parameters:
3476: +  mat - the factored matrix
3477: -  b - the right-hand-side vector

3479:    Output Parameter:
3480: .  x - the result vector

3482:    Notes:
3483:    The vectors b and x cannot be the same.  I.e., one cannot
3484:    call `MatSolve`(A,x,x).

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

3490:    Level: developer

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

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

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

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

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

3556:    Neighbor-wise Collective on A

3558:    Input Parameters:
3559: +  A - the factored matrix
3560: -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)

3562:    Output Parameter:
3563: .  X - the result matrix (dense matrix)

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

3569:    Level: developer

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

3588:   PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3589:   if (!A->ops->matsolve) {
3590:     PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name);
3591:     MatMatSolve_Basic(A, B, X, PETSC_FALSE);
3592:   } else PetscUseTypeMethod(A, matsolve, B, X);
3593:   PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3594:   PetscObjectStateIncrease((PetscObject)X);
3595:   return 0;
3596: }

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

3601:    Neighbor-wise Collective on A

3603:    Input Parameters:
3604: +  A - the factored matrix
3605: -  B - the right-hand-side matrix  (`MATDENSE` matrix)

3607:    Output Parameter:
3608: .  X - the result matrix (dense matrix)

3610:    Note:
3611:    The matrices B and X cannot be the same.  I.e., one cannot
3612:    call `MatMatSolveTranspose`(A,X,X).

3614:    Level: developer

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

3635:   PetscLogEventBegin(MAT_MatSolve, A, B, X, 0);
3636:   if (!A->ops->matsolvetranspose) {
3637:     PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name);
3638:     MatMatSolve_Basic(A, B, X, PETSC_TRUE);
3639:   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3640:   PetscLogEventEnd(MAT_MatSolve, A, B, X, 0);
3641:   PetscObjectStateIncrease((PetscObject)X);
3642:   return 0;
3643: }

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

3648:    Neighbor-wise Collective on A

3650:    Input Parameters:
3651: +  A - the factored matrix
3652: -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`

3654:    Output Parameter:
3655: .  X - the result matrix (dense matrix)

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

3661:    Level: developer

3663: .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3664: @*/
3665: PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3666: {

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

3682:   PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0);
3683:   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3684:   PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0);
3685:   PetscObjectStateIncrease((PetscObject)X);
3686:   return 0;
3687: }

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

3693:    Neighbor-wise Collective on mat

3695:    Input Parameters:
3696: +  mat - the factored matrix
3697: -  b - the right-hand-side vector

3699:    Output Parameter:
3700: .  x - the result vector

3702:    Notes:
3703:    `MatSolve()` should be used for most applications, as it performs
3704:    a forward solve followed by a backward solve.

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

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

3715:    Level: developer

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

3734:   PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0);
3735:   PetscUseTypeMethod(mat, forwardsolve, b, x);
3736:   PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0);
3737:   PetscObjectStateIncrease((PetscObject)x);
3738:   return 0;
3739: }

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

3745:    Neighbor-wise Collective on mat

3747:    Input Parameters:
3748: +  mat - the factored matrix
3749: -  b - the right-hand-side vector

3751:    Output Parameter:
3752: .  x - the result vector

3754:    Notes:
3755:    `MatSolve()` should be used for most applications, as it performs
3756:    a forward solve followed by a backward solve.

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

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

3767:    Level: developer

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

3786:   PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0);
3787:   PetscUseTypeMethod(mat, backwardsolve, b, x);
3788:   PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0);
3789:   PetscObjectStateIncrease((PetscObject)x);
3790:   return 0;
3791: }

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

3796:    Neighbor-wise Collective on mat

3798:    Input Parameters:
3799: +  mat - the factored matrix
3800: .  b - the right-hand-side vector
3801: -  y - the vector to be added to

3803:    Output Parameter:
3804: .  x - the result vector

3806:    Note:
3807:    The vectors b and x cannot be the same.  I.e., one cannot
3808:    call `MatSolveAdd`(A,x,y,x).

3810:    Level: developer

3812: .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3813: @*/
3814: PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3815: {
3816:   PetscScalar one = 1.0;
3817:   Vec         tmp;

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

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

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

3863:    Neighbor-wise Collective on mat

3865:    Input Parameters:
3866: +  mat - the factored matrix
3867: -  b - the right-hand-side vector

3869:    Output Parameter:
3870: .  x - the result vector

3872:    Notes:
3873:    The vectors b and x cannot be the same.  I.e., one cannot
3874:    call `MatSolveTranspose`(A,x,x).

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

3880:    Level: developer

3882: .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3883: @*/
3884: PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3885: {
3886:   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;

3897:   if (!mat->rmap->N && !mat->cmap->N) return 0;
3898:   MatCheckPreallocated(mat, 1);
3899:   PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0);
3900:   if (mat->factorerrortype) {
3901:     PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype);
3902:     VecSetInf(x);
3903:   } else {
3905:     (*f)(mat, b, x);
3906:   }
3907:   PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0);
3908:   PetscObjectStateIncrease((PetscObject)x);
3909:   return 0;
3910: }

3912: /*@
3913:    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3914:                       factored matrix.

3916:    Neighbor-wise Collective on mat

3918:    Input Parameters:
3919: +  mat - the factored matrix
3920: .  b - the right-hand-side vector
3921: -  y - the vector to be added to

3923:    Output Parameter:
3924: .  x - the result vector

3926:    Note:
3927:    The vectors b and x cannot be the same.  I.e., one cannot
3928:    call `MatSolveTransposeAdd`(A,x,y,x).

3930:    Level: developer

3932: .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
3933: @*/
3934: PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
3935: {
3936:   PetscScalar one = 1.0;
3937:   Vec         tmp;
3938:   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;

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

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

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

3984:    Neighbor-wise Collective on mat

3986:    Input Parameters:
3987: +  mat - the matrix
3988: .  b - the right hand side
3989: .  omega - the relaxation factor
3990: .  flag - flag indicating the type of SOR (see below)
3991: .  shift -  diagonal shift
3992: .  its - the number of iterations
3993: -  lits - the number of local iterations

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

3998:    SOR Flags:
3999: +     `SOR_FORWARD_SWEEP` - forward SOR
4000: .     `SOR_BACKWARD_SWEEP` - backward SOR
4001: .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4002: .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4003: .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4004: .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4005: .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4006: .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4007:          upper/lower triangular part of matrix to
4008:          vector (with omega)
4009: -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess

4011:    Notes:
4012:    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4013:    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4014:    on each processor.

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

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

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

4025:    Vectors x and b CANNOT be the same

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

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

4035:    Level: developer

4037: .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4038: @*/
4039: PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4040: {

4056:   MatCheckPreallocated(mat, 1);
4057:   PetscLogEventBegin(MAT_SOR, mat, b, x, 0);
4058:   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4059:   PetscLogEventEnd(MAT_SOR, mat, b, x, 0);
4060:   PetscObjectStateIncrease((PetscObject)x);
4061:   return 0;
4062: }

4064: /*
4065:       Default matrix copy routine.
4066: */
4067: PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4068: {
4069:   PetscInt           i, rstart = 0, rend = 0, nz;
4070:   const PetscInt    *cwork;
4071:   const PetscScalar *vwork;

4073:   if (B->assembled) MatZeroEntries(B);
4074:   if (str == SAME_NONZERO_PATTERN) {
4075:     MatGetOwnershipRange(A, &rstart, &rend);
4076:     for (i = rstart; i < rend; i++) {
4077:       MatGetRow(A, i, &nz, &cwork, &vwork);
4078:       MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES);
4079:       MatRestoreRow(A, i, &nz, &cwork, &vwork);
4080:     }
4081:   } else {
4082:     MatAYPX(B, 0.0, A, str);
4083:   }
4084:   MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);
4085:   MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);
4086:   return 0;
4087: }

4089: /*@
4090:    MatCopy - Copies a matrix to another matrix.

4092:    Collective on A

4094:    Input Parameters:
4095: +  A - the matrix
4096: -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`

4098:    Output Parameter:
4099: .  B - where the copy is put

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

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

4108:    Level: intermediate

4110: .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4111: @*/
4112: PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4113: {
4114:   PetscInt i;

4121:   MatCheckPreallocated(B, 2);
4125:              A->cmap->N, B->cmap->N);
4126:   MatCheckPreallocated(A, 1);
4127:   if (A == B) return 0;

4129:   PetscLogEventBegin(MAT_Copy, A, B, 0, 0);
4130:   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4131:   else MatCopy_Basic(A, B, str);

4133:   B->stencil.dim = A->stencil.dim;
4134:   B->stencil.noc = A->stencil.noc;
4135:   for (i = 0; i <= A->stencil.dim; i++) {
4136:     B->stencil.dims[i]   = A->stencil.dims[i];
4137:     B->stencil.starts[i] = A->stencil.starts[i];
4138:   }

4140:   PetscLogEventEnd(MAT_Copy, A, B, 0, 0);
4141:   PetscObjectStateIncrease((PetscObject)B);
4142:   return 0;
4143: }

4145: /*@C
4146:    MatConvert - Converts a matrix to another matrix, either of the same
4147:    or different type.

4149:    Collective on mat

4151:    Input Parameters:
4152: +  mat - the matrix
4153: .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4154:    same type as the original matrix.
4155: -  reuse - denotes if the destination matrix is to be created or reused.
4156:    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
4157:    `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).

4159:    Output Parameter:
4160: .  M - pointer to place new matrix

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

4167:    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4168:    the MPI communicator of the generated matrix is always the same as the communicator
4169:    of the input matrix.

4171:    Level: intermediate

4173: .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4174: @*/
4175: PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4176: {
4177:   PetscBool  sametype, issame, flg;
4178:   PetscBool3 issymmetric, ishermitian;
4179:   char       convname[256], mtype[256];
4180:   Mat        B;

4187:   MatCheckPreallocated(mat, 1);

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

4192:   PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype);
4193:   PetscStrcmp(newtype, "same", &issame);

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

4202:   /* Cache Mat options because some converters use MatHeaderReplace  */
4203:   issymmetric = mat->symmetric;
4204:   ishermitian = mat->hermitian;

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

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

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

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

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

4289:     /* 5) Use a really basic converter. */
4290:     PetscInfo(mat, "Using MatConvert_Basic\n");
4291:     conv = MatConvert_Basic;

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

4315:   /* Copy Mat options */
4316:   if (issymmetric == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE);
4317:   else if (issymmetric == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE);
4318:   if (ishermitian == PETSC_BOOL3_TRUE) MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE);
4319:   else if (ishermitian == PETSC_BOOL3_FALSE) MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE);
4320:   return 0;
4321: }

4323: /*@C
4324:    MatFactorGetSolverType - Returns name of the package providing the factorization routines

4326:    Not Collective

4328:    Input Parameter:
4329: .  mat - the matrix, must be a factored matrix

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

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

4338:    Level: intermediate

4340: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4341: @*/
4342: PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4343: {
4344:   PetscErrorCode (*conv)(Mat, MatSolverType *);

4350:   PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv);
4351:   if (conv) (*conv)(mat, type);
4352:   else *type = MATSOLVERPETSC;
4353:   return 0;
4354: }

4356: typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4357: struct _MatSolverTypeForSpecifcType {
4358:   MatType mtype;
4359:   /* no entry for MAT_FACTOR_NONE */
4360:   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4361:   MatSolverTypeForSpecifcType next;
4362: };

4364: typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4365: struct _MatSolverTypeHolder {
4366:   char                       *name;
4367:   MatSolverTypeForSpecifcType handlers;
4368:   MatSolverTypeHolder         next;
4369: };

4371: static MatSolverTypeHolder MatSolverTypeHolders = NULL;

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

4376:    Input Parameters:
4377: +    package - name of the package, for example petsc or superlu
4378: .    mtype - the matrix type that works with this package
4379: .    ftype - the type of factorization supported by the package
4380: -    createfactor - routine that will create the factored matrix ready to be used

4382:     Level: developer

4384: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4385: @*/
4386: PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4387: {
4388:   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4389:   PetscBool                   flg;
4390:   MatSolverTypeForSpecifcType inext, iprev = NULL;

4392:   MatInitializePackage();
4393:   if (!next) {
4394:     PetscNew(&MatSolverTypeHolders);
4395:     PetscStrallocpy(package, &MatSolverTypeHolders->name);
4396:     PetscNew(&MatSolverTypeHolders->handlers);
4397:     PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype);
4398:     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4399:     return 0;
4400:   }
4401:   while (next) {
4402:     PetscStrcasecmp(package, next->name, &flg);
4403:     if (flg) {
4405:       inext = next->handlers;
4406:       while (inext) {
4407:         PetscStrcasecmp(mtype, inext->mtype, &flg);
4408:         if (flg) {
4409:           inext->createfactor[(int)ftype - 1] = createfactor;
4410:           return 0;
4411:         }
4412:         iprev = inext;
4413:         inext = inext->next;
4414:       }
4415:       PetscNew(&iprev->next);
4416:       PetscStrallocpy(mtype, (char **)&iprev->next->mtype);
4417:       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4418:       return 0;
4419:     }
4420:     prev = next;
4421:     next = next->next;
4422:   }
4423:   PetscNew(&prev->next);
4424:   PetscStrallocpy(package, &prev->next->name);
4425:   PetscNew(&prev->next->handlers);
4426:   PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype);
4427:   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4428:   return 0;
4429: }

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

4434:    Input Parameters:
4435: +    type - name of the package, for example petsc or superlu
4436: .    ftype - the type of factorization supported by the type
4437: -    mtype - the matrix type that works with this type

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

4444:     Level: developer

4446: .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4447: @*/
4448: PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4449: {
4450:   MatSolverTypeHolder         next = MatSolverTypeHolders;
4451:   PetscBool                   flg;
4452:   MatSolverTypeForSpecifcType inext;

4454:   if (foundtype) *foundtype = PETSC_FALSE;
4455:   if (foundmtype) *foundmtype = PETSC_FALSE;
4456:   if (createfactor) *createfactor = NULL;

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

4511: PetscErrorCode MatSolverTypeDestroy(void)
4512: {
4513:   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4514:   MatSolverTypeForSpecifcType inext, iprev;

4516:   while (next) {
4517:     PetscFree(next->name);
4518:     inext = next->handlers;
4519:     while (inext) {
4520:       PetscFree(inext->mtype);
4521:       iprev = inext;
4522:       inext = inext->next;
4523:       PetscFree(iprev);
4524:     }
4525:     prev = next;
4526:     next = next->next;
4527:     PetscFree(prev);
4528:   }
4529:   MatSolverTypeHolders = NULL;
4530:   return 0;
4531: }

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

4536:    Logically Collective on mat

4538:    Input Parameters:
4539: .  mat - the matrix

4541:    Output Parameters:
4542: .  flg - `PETSC_TRUE` if uses the ordering

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

4548:    Level: developer

4550: .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4551: @*/
4552: PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4553: {
4554:   *flg = mat->canuseordering;
4555:   return 0;
4556: }

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

4561:    Logically Collective on mat

4563:    Input Parameters:
4564: .  mat - the matrix obtained with `MatGetFactor()`

4566:    Output Parameters:
4567: .  otype - the preferred type

4569:    Level: developer

4571: .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4572: @*/
4573: PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4574: {
4575:   *otype = mat->preferredordering[ftype];
4577:   return 0;
4578: }

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

4583:    Collective on mat

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

4590:    Output Parameters:
4591: .  f - the factor matrix used with MatXXFactorSymbolic() calls

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

4597:    Notes:
4598:      Users usually access the factorization solvers via `KSP`

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

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

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

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

4612:    Level: intermediate

4614: .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4615:           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4616: @*/
4617: PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4618: {
4619:   PetscBool foundtype, foundmtype;
4620:   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);


4626:   MatCheckPreallocated(mat, 1);

4628:   MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv);
4629:   if (!foundtype) {
4630:     if (type) {
4631:       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],
4632:               ((PetscObject)mat)->type_name, type);
4633:     } else {
4634:       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);
4635:     }
4636:   }

4640:   (*conv)(mat, ftype, f);
4641:   if (mat->factorprefix) MatSetOptionsPrefix(*f, mat->factorprefix);
4642:   return 0;
4643: }

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

4648:    Not Collective

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

4655:    Output Parameter:
4656: .    flg - PETSC_TRUE if the factorization is available

4658:    Notes:
4659:       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4660:      such as pastix, superlu, mumps etc.

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

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

4667:    Level: intermediate

4669: .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4670:           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4671: @*/
4672: PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4673: {
4674:   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);


4681:   MatCheckPreallocated(mat, 1);

4683:   MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv);
4684:   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4685:   return 0;
4686: }

4688: /*@
4689:    MatDuplicate - Duplicates a matrix including the non-zero structure.

4691:    Collective on mat

4693:    Input Parameters:
4694: +  mat - the matrix
4695: -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4696:         See the manual page for `MatDuplicateOption()` for an explanation of these options.

4698:    Output Parameter:
4699: .  M - pointer to place new matrix

4701:    Level: intermediate

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

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

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

4712: .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4713: @*/
4714: PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4715: {
4716:   Mat         B;
4717:   VecType     vtype;
4718:   PetscInt    i;
4719:   PetscObject dm;
4720:   void (*viewf)(void);

4727:   MatCheckPreallocated(mat, 1);

4729:   *M = NULL;
4730:   PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0);
4731:   PetscUseTypeMethod(mat, duplicate, op, M);
4732:   PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0);
4733:   B = *M;

4735:   MatGetOperation(mat, MATOP_VIEW, &viewf);
4736:   if (viewf) MatSetOperation(B, MATOP_VIEW, viewf);
4737:   MatGetVecType(mat, &vtype);
4738:   MatSetVecType(B, vtype);

4740:   B->stencil.dim = mat->stencil.dim;
4741:   B->stencil.noc = mat->stencil.noc;
4742:   for (i = 0; i <= mat->stencil.dim; i++) {
4743:     B->stencil.dims[i]   = mat->stencil.dims[i];
4744:     B->stencil.starts[i] = mat->stencil.starts[i];
4745:   }

4747:   B->nooffproczerorows = mat->nooffproczerorows;
4748:   B->nooffprocentries  = mat->nooffprocentries;

4750:   PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm);
4751:   if (dm) PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm);
4752:   PetscObjectStateIncrease((PetscObject)B);
4753:   return 0;
4754: }

4756: /*@
4757:    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`

4759:    Logically Collective on mat

4761:    Input Parameters:
4762: +  mat - the matrix
4763: -  v - the vector for storing the diagonal

4765:    Output Parameter:
4766: .  v - the diagonal of the matrix

4768:    Level: intermediate

4770:    Note:
4771:    Currently only correct in parallel for square matrices.

4773: .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4774: @*/
4775: PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4776: {
4781:   MatCheckPreallocated(mat, 1);

4783:   PetscUseTypeMethod(mat, getdiagonal, v);
4784:   PetscObjectStateIncrease((PetscObject)v);
4785:   return 0;
4786: }

4788: /*@C
4789:    MatGetRowMin - Gets the minimum value (of the real part) of each
4790:         row of the matrix

4792:    Logically Collective on mat

4794:    Input Parameter:
4795: .  mat - the matrix

4797:    Output Parameters:
4798: +  v - the vector for storing the maximums
4799: -  idx - the indices of the column found for each row (optional)

4801:    Level: intermediate

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

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

4809: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4810:           `MatGetRowMax()`
4811: @*/
4812: PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4813: {

4819:   if (!mat->cmap->N) {
4820:     VecSet(v, PETSC_MAX_REAL);
4821:     if (idx) {
4822:       PetscInt i, m = mat->rmap->n;
4823:       for (i = 0; i < m; i++) idx[i] = -1;
4824:     }
4825:   } else {
4826:     MatCheckPreallocated(mat, 1);
4827:   }
4828:   PetscUseTypeMethod(mat, getrowmin, v, idx);
4829:   PetscObjectStateIncrease((PetscObject)v);
4830:   return 0;
4831: }

4833: /*@C
4834:    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4835:         row of the matrix

4837:    Logically Collective on mat

4839:    Input Parameter:
4840: .  mat - the matrix

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

4846:    Level: intermediate

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

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

4854: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4855: @*/
4856: PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4857: {

4864:   if (!mat->cmap->N) {
4865:     VecSet(v, 0.0);
4866:     if (idx) {
4867:       PetscInt i, m = mat->rmap->n;
4868:       for (i = 0; i < m; i++) idx[i] = -1;
4869:     }
4870:   } else {
4871:     MatCheckPreallocated(mat, 1);
4872:     if (idx) PetscArrayzero(idx, mat->rmap->n);
4873:     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4874:   }
4875:   PetscObjectStateIncrease((PetscObject)v);
4876:   return 0;
4877: }

4879: /*@C
4880:    MatGetRowMax - Gets the maximum value (of the real part) of each
4881:         row of the matrix

4883:    Logically Collective on mat

4885:    Input Parameter:
4886: .  mat - the matrix

4888:    Output Parameters:
4889: +  v - the vector for storing the maximums
4890: -  idx - the indices of the column found for each row (optional)

4892:    Level: intermediate

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

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

4900: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4901: @*/
4902: PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
4903: {

4909:   if (!mat->cmap->N) {
4910:     VecSet(v, PETSC_MIN_REAL);
4911:     if (idx) {
4912:       PetscInt i, m = mat->rmap->n;
4913:       for (i = 0; i < m; i++) idx[i] = -1;
4914:     }
4915:   } else {
4916:     MatCheckPreallocated(mat, 1);
4917:     PetscUseTypeMethod(mat, getrowmax, v, idx);
4918:   }
4919:   PetscObjectStateIncrease((PetscObject)v);
4920:   return 0;
4921: }

4923: /*@C
4924:    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4925:         row of the matrix

4927:    Logically Collective on mat

4929:    Input Parameter:
4930: .  mat - the matrix

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

4936:    Level: intermediate

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

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

4944: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4945: @*/
4946: PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
4947: {

4953:   if (!mat->cmap->N) {
4954:     VecSet(v, 0.0);
4955:     if (idx) {
4956:       PetscInt i, m = mat->rmap->n;
4957:       for (i = 0; i < m; i++) idx[i] = -1;
4958:     }
4959:   } else {
4960:     MatCheckPreallocated(mat, 1);
4961:     if (idx) PetscArrayzero(idx, mat->rmap->n);
4962:     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
4963:   }
4964:   PetscObjectStateIncrease((PetscObject)v);
4965:   return 0;
4966: }

4968: /*@
4969:    MatGetRowSum - Gets the sum of each row of the matrix

4971:    Logically or Neighborhood Collective on mat

4973:    Input Parameters:
4974: .  mat - the matrix

4976:    Output Parameter:
4977: .  v - the vector for storing the sum of rows

4979:    Level: intermediate

4981:    Notes:
4982:     This code is slow since it is not currently specialized for different formats

4984: .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
4985: @*/
4986: PetscErrorCode MatGetRowSum(Mat mat, Vec v)
4987: {
4988:   Vec ones;

4994:   MatCheckPreallocated(mat, 1);
4995:   MatCreateVecs(mat, &ones, NULL);
4996:   VecSet(ones, 1.);
4997:   MatMult(mat, ones, v);
4998:   VecDestroy(&ones);
4999:   return 0;
5000: }

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

5006:    Collective on mat

5008:    Input Parameter:
5009: .  mat - the matrix to provide the transpose

5011:    Output Parameter:
5012: .  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

5014:    Level: advanced

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

5020: .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5021: @*/
5022: PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5023: {
5024:   PetscContainer  rB = NULL;
5025:   MatParentState *rb = NULL;

5027:   PetscNew(&rb);
5028:   rb->id    = ((PetscObject)mat)->id;
5029:   rb->state = 0;
5030:   MatGetNonzeroState(mat, &rb->nonzerostate);
5031:   PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB);
5032:   PetscContainerSetPointer(rB, rb);
5033:   PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault);
5034:   PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB);
5035:   PetscObjectDereference((PetscObject)rB);
5036:   return 0;
5037: }

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

5042:    Collective on mat

5044:    Input Parameters:
5045: +  mat - the matrix to transpose
5046: -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`

5048:    Output Parameter:
5049: .  B - the transpose

5051:    Notes:
5052:      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B

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

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

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

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

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

5065:    Level: intermediate

5067: .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5068:           `MatTransposeSymbolic()`
5069: @*/
5070: PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5071: {
5072:   PetscContainer  rB = NULL;
5073:   MatParentState *rb = NULL;

5081:   MatCheckPreallocated(mat, 1);
5082:   if (reuse == MAT_REUSE_MATRIX) {
5083:     PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5085:     PetscContainerGetPointer(rB, (void **)&rb);
5087:     if (rb->state == ((PetscObject)mat)->state) return 0;
5088:   }

5090:   PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0);
5091:   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5092:     PetscUseTypeMethod(mat, transpose, reuse, B);
5093:     PetscObjectStateIncrease((PetscObject)*B);
5094:   }
5095:   PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0);

5097:   if (reuse == MAT_INITIAL_MATRIX) MatTransposeSetPrecursor(mat, *B);
5098:   if (reuse != MAT_INPLACE_MATRIX) {
5099:     PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB);
5100:     PetscContainerGetPointer(rB, (void **)&rb);
5101:     rb->state        = ((PetscObject)mat)->state;
5102:     rb->nonzerostate = mat->nonzerostate;
5103:   }
5104:   return 0;
5105: }

5107: /*@
5108:    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.

5110:    Collective on A

5112:    Input Parameters:
5113: .  A - the matrix to transpose

5115:    Output Parameter:
5116: .  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
5117:       numerical portion.

5119:    Level: intermediate

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

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

5137:   MatTransposeSetPrecursor(A, *B);
5138:   return 0;
5139: }

5141: PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5142: {
5143:   PetscContainer  rB;
5144:   MatParentState *rb;

5150:   PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB);
5152:   PetscContainerGetPointer(rB, (void **)&rb);
5155:   return 0;
5156: }

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

5162:    Collective on A

5164:    Input Parameters:
5165: +  A - the matrix to test
5166: -  B - the matrix to test against, this can equal the first parameter

5168:    Output Parameters:
5169: .  flg - the result

5171:    Notes:
5172:    Only available for `MATAIJ` matrices.

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

5177:    Level: intermediate

5179: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5180: @*/
5181: PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5182: {
5183:   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);

5188:   PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f);
5189:   PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g);
5190:   *flg = PETSC_FALSE;
5191:   if (f && g) {
5193:     (*f)(A, B, tol, flg);
5194:   } else {
5195:     MatType mattype;

5197:     MatGetType(f ? B : A, &mattype);
5198:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5199:   }
5200:   return 0;
5201: }

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

5206:    Collective on mat

5208:    Input Parameters:
5209: +  mat - the matrix to transpose and complex conjugate
5210: -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`

5212:    Output Parameter:
5213: .  B - the Hermitian transpose

5215:    Level: intermediate

5217: .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5218: @*/
5219: PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5220: {
5221:   MatTranspose(mat, reuse, B);
5222: #if defined(PETSC_USE_COMPLEX)
5223:   MatConjugate(*B);
5224: #endif
5225:   return 0;
5226: }

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

5231:    Collective on A

5233:    Input Parameters:
5234: +  A - the matrix to test
5235: -  B - the matrix to test against, this can equal the first parameter

5237:    Output Parameters:
5238: .  flg - the result

5240:    Notes:
5241:    Only available for `MATAIJ` matrices.

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

5247:    Level: intermediate

5249: .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5250: @*/
5251: PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5252: {
5253:   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);

5258:   PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f);
5259:   PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g);
5260:   if (f && g) {
5262:     (*f)(A, B, tol, flg);
5263:   }
5264:   return 0;
5265: }

5267: /*@
5268:    MatPermute - Creates a new matrix with rows and columns permuted from the
5269:    original.

5271:    Collective on mat

5273:    Input Parameters:
5274: +  mat - the matrix to permute
5275: .  row - row permutation, each processor supplies only the permutation for its rows
5276: -  col - column permutation, each processor supplies only the permutation for its columns

5278:    Output Parameters:
5279: .  B - the permuted matrix

5281:    Level: advanced

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

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

5292: .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5293: @*/
5294: PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5295: {
5306:   MatCheckPreallocated(mat, 1);

5308:   if (mat->ops->permute) {
5309:     PetscUseTypeMethod(mat, permute, row, col, B);
5310:     PetscObjectStateIncrease((PetscObject)*B);
5311:   } else {
5312:     MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B);
5313:   }
5314:   return 0;
5315: }

5317: /*@
5318:    MatEqual - Compares two matrices.

5320:    Collective on A

5322:    Input Parameters:
5323: +  A - the first matrix
5324: -  B - the second matrix

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

5329:    Level: intermediate

5331: .seealso: `Mat`
5332: @*/
5333: PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5334: {
5341:   MatCheckPreallocated(A, 1);
5342:   MatCheckPreallocated(B, 2);
5346:              B->cmap->N);
5347:   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5348:     PetscUseTypeMethod(A, equal, B, flg);
5349:   } else {
5350:     MatMultEqual(A, B, 10, flg);
5351:   }
5352:   return 0;
5353: }

5355: /*@
5356:    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5357:    matrices that are stored as vectors.  Either of the two scaling
5358:    matrices can be NULL.

5360:    Collective on mat

5362:    Input Parameters:
5363: +  mat - the matrix to be scaled
5364: .  l - the left scaling vector (or NULL)
5365: -  r - the right scaling vector (or NULL)

5367:    Note:
5368:    `MatDiagonalScale()` computes A = LAR, where
5369:    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5370:    The L scales the rows of the matrix, the R scales the columns of the matrix.

5372:    Level: intermediate

5374: .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5375: @*/
5376: PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5377: {
5380:   if (l) {
5383:   }
5384:   if (r) {
5387:   }
5390:   MatCheckPreallocated(mat, 1);
5391:   if (!l && !r) return 0;

5393:   PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5394:   PetscUseTypeMethod(mat, diagonalscale, l, r);
5395:   PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5396:   PetscObjectStateIncrease((PetscObject)mat);
5397:   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5398:   return 0;
5399: }

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

5404:     Logically Collective on mat

5406:     Input Parameters:
5407: +   mat - the matrix to be scaled
5408: -   a  - the scaling value

5410:     Output Parameter:
5411: .   mat - the scaled matrix

5413:     Level: intermediate

5415: .seealso: `Mat`, `MatDiagonalScale()`
5416: @*/
5417: PetscErrorCode MatScale(Mat mat, PetscScalar a)
5418: {
5425:   MatCheckPreallocated(mat, 1);

5427:   PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
5428:   if (a != (PetscScalar)1.0) {
5429:     PetscUseTypeMethod(mat, scale, a);
5430:     PetscObjectStateIncrease((PetscObject)mat);
5431:   }
5432:   PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
5433:   return 0;
5434: }

5436: /*@
5437:    MatNorm - Calculates various norms of a matrix.

5439:    Collective on mat

5441:    Input Parameters:
5442: +  mat - the matrix
5443: -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`

5445:    Output Parameter:
5446: .  nrm - the resulting norm

5448:    Level: intermediate

5450: .seealso: `Mat`
5451: @*/
5452: PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5453: {

5460:   MatCheckPreallocated(mat, 1);

5462:   PetscUseTypeMethod(mat, norm, type, nrm);
5463:   return 0;
5464: }

5466: /*
5467:      This variable is used to prevent counting of MatAssemblyBegin() that
5468:    are called from within a MatAssemblyEnd().
5469: */
5470: static PetscInt MatAssemblyEnd_InUse = 0;
5471: /*@
5472:    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5473:    be called after completing all calls to `MatSetValues()`.

5475:    Collective on mat

5477:    Input Parameters:
5478: +  mat - the matrix
5479: -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`

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

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

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

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

5497:    Level: beginner

5499: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5500: @*/
5501: PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5502: {
5505:   MatCheckPreallocated(mat, 1);
5507:   if (mat->assembled) {
5508:     mat->was_assembled = PETSC_TRUE;
5509:     mat->assembled     = PETSC_FALSE;
5510:   }

5512:   if (!MatAssemblyEnd_InUse) {
5513:     PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0);
5514:     PetscTryTypeMethod(mat, assemblybegin, type);
5515:     PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0);
5516:   } else PetscTryTypeMethod(mat, assemblybegin, type);
5517:   return 0;
5518: }

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

5524:    Not Collective

5526:    Input Parameter:
5527: .  mat - the matrix

5529:    Output Parameter:
5530: .  assembled - `PETSC_TRUE` or `PETSC_FALSE`

5532:    Level: advanced

5534: .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5535: @*/
5536: PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5537: {
5540:   *assembled = mat->assembled;
5541:   return 0;
5542: }

5544: /*@
5545:    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5546:    be called after `MatAssemblyBegin()`.

5548:    Collective on Mat

5550:    Input Parameters:
5551: +  mat - the matrix
5552: -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`

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

5567:    Level: beginner

5569: .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5570: @*/
5571: PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5572: {
5573:   static PetscInt inassm = 0;
5574:   PetscBool       flg    = PETSC_FALSE;


5579:   inassm++;
5580:   MatAssemblyEnd_InUse++;
5581:   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5582:     PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0);
5583:     PetscTryTypeMethod(mat, assemblyend, type);
5584:     PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0);
5585:   } else PetscTryTypeMethod(mat, assemblyend, type);

5587:   /* Flush assembly is not a true assembly */
5588:   if (type != MAT_FLUSH_ASSEMBLY) {
5589:     if (mat->num_ass) {
5590:       if (!mat->symmetry_eternal) {
5591:         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5592:         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5593:       }
5594:       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5595:       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5596:     }
5597:     mat->num_ass++;
5598:     mat->assembled        = PETSC_TRUE;
5599:     mat->ass_nonzerostate = mat->nonzerostate;
5600:   }

5602:   mat->insertmode = NOT_SET_VALUES;
5603:   MatAssemblyEnd_InUse--;
5604:   PetscObjectStateIncrease((PetscObject)mat);
5605:   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5606:     MatViewFromOptions(mat, NULL, "-mat_view");

5608:     if (mat->checksymmetryonassembly) {
5609:       MatIsSymmetric(mat, mat->checksymmetrytol, &flg);
5610:       if (flg) {
5611:         PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5612:       } else {
5613:         PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol);
5614:       }
5615:     }
5616:     if (mat->nullsp && mat->checknullspaceonassembly) MatNullSpaceTest(mat->nullsp, mat, NULL);
5617:   }
5618:   inassm--;
5619:   return 0;
5620: }

5622: /*@
5623:    MatSetOption - Sets a parameter option for a matrix. Some options
5624:    may be specific to certain storage formats.  Some options
5625:    determine how values will be inserted (or added). Sorted,
5626:    row-oriented input will generally assemble the fastest. The default
5627:    is row-oriented.

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

5631:    Input Parameters:
5632: +  mat - the matrix
5633: .  option - the option, one of those listed below (and possibly others),
5634: -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)

5636:   Options Describing Matrix Structure:
5637: +    `MAT_SPD` - symmetric positive definite
5638: .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5639: .    `MAT_HERMITIAN` - transpose is the complex conjugation
5640: .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5641: .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5642: .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5643: -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix

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

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

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

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

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

5673:    Some options are relevant only for particular matrix types and
5674:    are thus ignored by others.  Other options are not supported by
5675:    certain matrix types and will generate an error message if set.

5677:    If using a Fortran 77 module to compute a matrix, one may need to
5678:    use the column-oriented option (or convert to the row-oriented
5679:    format).

5681:    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5682:    that would generate a new entry in the nonzero structure is instead
5683:    ignored.  Thus, if memory has not alredy been allocated for this particular
5684:    data, then the insertion is ignored. For dense matrices, in which
5685:    the entire array is allocated, no entries are ever ignored.
5686:    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction

5688:    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5689:    that would generate a new entry in the nonzero structure instead produces
5690:    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

5692:    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5693:    that would generate a new entry that has not been preallocated will
5694:    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5695:    only.) This is a useful flag when debugging matrix memory preallocation.
5696:    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction

5698:    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5699:    other processors should be dropped, rather than stashed.
5700:    This is useful if you know that the "owning" processor is also
5701:    always generating the correct matrix entries, so that PETSc need
5702:    not transfer duplicate entries generated on another processor.

5704:    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5705:    searches during matrix assembly. When this flag is set, the hash table
5706:    is created during the first matrix assembly. This hash table is
5707:    used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5708:    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5709:    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5710:    supported by` MATMPIBAIJ` format only.

5712:    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5713:    are kept in the nonzero structure

5715:    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5716:    a zero location in the matrix

5718:    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types

5720:    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5721:         zero row routines and thus improves performance for very large process counts.

5723:    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5724:         part of the matrix (since they should match the upper triangular part).

5726:    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5727:                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5728:                      with finite difference schemes with non-periodic boundary conditions.

5730:    Developer Note:
5731:    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5732:    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5733:    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5734:    not changed.

5736:    Level: intermediate

5738: .seealso: `MatOption`, `Mat`, `MatGetOption()`
5739: @*/
5740: PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5741: {
5743:   if (op > 0) {
5746:   }


5750:   switch (op) {
5751:   case MAT_FORCE_DIAGONAL_ENTRIES:
5752:     mat->force_diagonals = flg;
5753:     return 0;
5754:   case MAT_NO_OFF_PROC_ENTRIES:
5755:     mat->nooffprocentries = flg;
5756:     return 0;
5757:   case MAT_SUBSET_OFF_PROC_ENTRIES:
5758:     mat->assembly_subset = flg;
5759:     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5760: #if !defined(PETSC_HAVE_MPIUNI)
5761:       MatStashScatterDestroy_BTS(&mat->stash);
5762: #endif
5763:       mat->stash.first_assembly_done = PETSC_FALSE;
5764:     }
5765:     return 0;
5766:   case MAT_NO_OFF_PROC_ZERO_ROWS:
5767:     mat->nooffproczerorows = flg;
5768:     return 0;
5769:   case MAT_SPD:
5770:     if (flg) {
5771:       mat->spd                    = PETSC_BOOL3_TRUE;
5772:       mat->symmetric              = PETSC_BOOL3_TRUE;
5773:       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5774:     } else {
5775:       mat->spd = PETSC_BOOL3_FALSE;
5776:     }
5777:     break;
5778:   case MAT_SYMMETRIC:
5779:     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5780:     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5781: #if !defined(PETSC_USE_COMPLEX)
5782:     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5783: #endif
5784:     break;
5785:   case MAT_HERMITIAN:
5786:     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5787:     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5788: #if !defined(PETSC_USE_COMPLEX)
5789:     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5790: #endif
5791:     break;
5792:   case MAT_STRUCTURALLY_SYMMETRIC:
5793:     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5794:     break;
5795:   case MAT_SYMMETRY_ETERNAL:
5797:     mat->symmetry_eternal = flg;
5798:     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5799:     break;
5800:   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5802:     mat->structural_symmetry_eternal = flg;
5803:     break;
5804:   case MAT_SPD_ETERNAL:
5806:     mat->spd_eternal = flg;
5807:     if (flg) {
5808:       mat->structural_symmetry_eternal = PETSC_TRUE;
5809:       mat->symmetry_eternal            = PETSC_TRUE;
5810:     }
5811:     break;
5812:   case MAT_STRUCTURE_ONLY:
5813:     mat->structure_only = flg;
5814:     break;
5815:   case MAT_SORTED_FULL:
5816:     mat->sortedfull = flg;
5817:     break;
5818:   default:
5819:     break;
5820:   }
5821:   PetscTryTypeMethod(mat, setoption, op, flg);
5822:   return 0;
5823: }

5825: /*@
5826:    MatGetOption - Gets a parameter option that has been set for a matrix.

5828:    Logically Collective on mat

5830:    Input Parameters:
5831: +  mat - the matrix
5832: -  option - the option, this only responds to certain options, check the code for which ones

5834:    Output Parameter:
5835: .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)

5837:     Notes:
5838:     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.

5840:     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`, or
5841:     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`

5843:    Level: intermediate

5845: .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`,
5846:     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5847: @*/
5848: PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5849: {


5856:   switch (op) {
5857:   case MAT_NO_OFF_PROC_ENTRIES:
5858:     *flg = mat->nooffprocentries;
5859:     break;
5860:   case MAT_NO_OFF_PROC_ZERO_ROWS:
5861:     *flg = mat->nooffproczerorows;
5862:     break;
5863:   case MAT_SYMMETRIC:
5864:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5865:     break;
5866:   case MAT_HERMITIAN:
5867:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5868:     break;
5869:   case MAT_STRUCTURALLY_SYMMETRIC:
5870:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5871:     break;
5872:   case MAT_SPD:
5873:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
5874:     break;
5875:   case MAT_SYMMETRY_ETERNAL:
5876:     *flg = mat->symmetry_eternal;
5877:     break;
5878:   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5879:     *flg = mat->symmetry_eternal;
5880:     break;
5881:   default:
5882:     break;
5883:   }
5884:   return 0;
5885: }

5887: /*@
5888:    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5889:    this routine retains the old nonzero structure.

5891:    Logically Collective on mat

5893:    Input Parameters:
5894: .  mat - the matrix

5896:    Level: intermediate

5898:    Note:
5899:     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.
5900:    See the Performance chapter of the users manual for information on preallocating matrices.

5902: .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
5903: @*/
5904: PetscErrorCode MatZeroEntries(Mat mat)
5905: {
5910:   MatCheckPreallocated(mat, 1);

5912:   PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0);
5913:   PetscUseTypeMethod(mat, zeroentries);
5914:   PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0);
5915:   PetscObjectStateIncrease((PetscObject)mat);
5916:   return 0;
5917: }

5919: /*@
5920:    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5921:    of a set of rows and columns of a matrix.

5923:    Collective on mat

5925:    Input Parameters:
5926: +  mat - the matrix
5927: .  numRows - the number of rows to remove
5928: .  rows - the global row indices
5929: .  diag - value put in the diagonal of the eliminated rows
5930: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5931: -  b - optional vector of right hand side, that will be adjusted by provided solution

5933:    Notes:
5934:    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.

5936:    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5937:    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

5939:    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5940:    Krylov method to take advantage of the known solution on the zeroed rows.

5942:    For the parallel case, all processes that share the matrix (i.e.,
5943:    those in the communicator used for matrix creation) MUST call this
5944:    routine, regardless of whether any rows being zeroed are owned by
5945:    them.

5947:    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.

5949:    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5950:    list only rows local to itself).

5952:    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.

5954:    Level: intermediate

5956: .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5957:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5958: @*/
5959: PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
5960: {
5966:   MatCheckPreallocated(mat, 1);

5968:   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
5969:   MatViewFromOptions(mat, NULL, "-mat_view");
5970:   PetscObjectStateIncrease((PetscObject)mat);
5971:   return 0;
5972: }

5974: /*@
5975:    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5976:    of a set of rows and columns of a matrix.

5978:    Collective on mat

5980:    Input Parameters:
5981: +  mat - the matrix
5982: .  is - the rows to zero
5983: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5984: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5985: -  b - optional vector of right hand side, that will be adjusted by provided solution

5987:    Note:
5988:    See `MatZeroRowsColumns()` for details on how this routine operates.

5990:    Level: intermediate

5992: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5993:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
5994: @*/
5995: PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
5996: {
5997:   PetscInt        numRows;
5998:   const PetscInt *rows;

6004:   ISGetLocalSize(is, &numRows);
6005:   ISGetIndices(is, &rows);
6006:   MatZeroRowsColumns(mat, numRows, rows, diag, x, b);
6007:   ISRestoreIndices(is, &rows);
6008:   return 0;
6009: }

6011: /*@
6012:    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6013:    of a set of rows of a matrix.

6015:    Collective on mat

6017:    Input Parameters:
6018: +  mat - the matrix
6019: .  numRows - the number of rows to remove
6020: .  rows - the global row indices
6021: .  diag - value put in the diagonal of the eliminated rows
6022: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6023: -  b - optional vector of right hand side, that will be adjusted by provided solution

6025:    Notes:
6026:    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.

6028:    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.

6030:    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6031:    Krylov method to take advantage of the known solution on the zeroed rows.

6033:    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reducing problem (after completely eliminating the zeroed rows and their corresponding columns)
6034:    from the matrix.

6036:    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6037:    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
6038:    formats this does not alter the nonzero structure.

6040:    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6041:    of the matrix is not changed the values are
6042:    merely zeroed.

6044:    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6045:    formats can optionally remove the main diagonal entry from the
6046:    nonzero structure as well, by passing 0.0 as the final argument).

6048:    For the parallel case, all processes that share the matrix (i.e.,
6049:    those in the communicator used for matrix creation) MUST call this
6050:    routine, regardless of whether any rows being zeroed are owned by
6051:    them.

6053:    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6054:    list only rows local to itself).

6056:    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6057:    owns that are to be zeroed. This saves a global synchronization in the implementation.

6059:    Level: intermediate

6061: .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6062:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6063: @*/
6064: PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6065: {
6071:   MatCheckPreallocated(mat, 1);

6073:   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6074:   MatViewFromOptions(mat, NULL, "-mat_view");
6075:   PetscObjectStateIncrease((PetscObject)mat);
6076:   return 0;
6077: }

6079: /*@
6080:    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6081:    of a set of rows of a matrix.

6083:    Collective on Mat

6085:    Input Parameters:
6086: +  mat - the matrix
6087: .  is - index set of rows to remove (if NULL then no row is removed)
6088: .  diag - value put in all diagonals of eliminated rows
6089: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6090: -  b - optional vector of right hand side, that will be adjusted by provided solution

6092:    Note:
6093:    See `MatZeroRows()` for details on how this routine operates.

6095:    Level: intermediate

6097: .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6098:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6099: @*/
6100: PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6101: {
6102:   PetscInt        numRows = 0;
6103:   const PetscInt *rows    = NULL;

6107:   if (is) {
6109:     ISGetLocalSize(is, &numRows);
6110:     ISGetIndices(is, &rows);
6111:   }
6112:   MatZeroRows(mat, numRows, rows, diag, x, b);
6113:   if (is) ISRestoreIndices(is, &rows);
6114:   return 0;
6115: }

6117: /*@
6118:    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6119:    of a set of rows of a matrix. These rows must be local to the process.

6121:    Collective on mat

6123:    Input Parameters:
6124: +  mat - the matrix
6125: .  numRows - the number of rows to remove
6126: .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6127: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6128: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6129: -  b - optional vector of right hand side, that will be adjusted by provided solution

6131:    Notes:
6132:    See `MatZeroRows()` for details on how this routine operates.

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

6136:    In Fortran idxm and idxn should be declared as
6137: $     MatStencil idxm(4,m)
6138:    and the values inserted using
6139: $    idxm(MatStencil_i,1) = i
6140: $    idxm(MatStencil_j,1) = j
6141: $    idxm(MatStencil_k,1) = k
6142: $    idxm(MatStencil_c,1) = c
6143:    etc

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

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

6153:    Level: intermediate

6155: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6156:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6157: @*/
6158: PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6159: {
6160:   PetscInt  dim    = mat->stencil.dim;
6161:   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6162:   PetscInt *dims   = mat->stencil.dims + 1;
6163:   PetscInt *starts = mat->stencil.starts;
6164:   PetscInt *dxm    = (PetscInt *)rows;
6165:   PetscInt *jdxm, i, j, tmp, numNewRows = 0;


6171:   PetscMalloc1(numRows, &jdxm);
6172:   for (i = 0; i < numRows; ++i) {
6173:     /* Skip unused dimensions (they are ordered k, j, i, c) */
6174:     for (j = 0; j < 3 - sdim; ++j) dxm++;
6175:     /* Local index in X dir */
6176:     tmp = *dxm++ - starts[0];
6177:     /* Loop over remaining dimensions */
6178:     for (j = 0; j < dim - 1; ++j) {
6179:       /* If nonlocal, set index to be negative */
6180:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6181:       /* Update local index */
6182:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6183:     }
6184:     /* Skip component slot if necessary */
6185:     if (mat->stencil.noc) dxm++;
6186:     /* Local row number */
6187:     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6188:   }
6189:   MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b);
6190:   PetscFree(jdxm);
6191:   return 0;
6192: }

6194: /*@
6195:    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6196:    of a set of rows and columns of a matrix.

6198:    Collective on mat

6200:    Input Parameters:
6201: +  mat - the matrix
6202: .  numRows - the number of rows/columns to remove
6203: .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6204: .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6205: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6206: -  b - optional vector of right hand side, that will be adjusted by provided solution

6208:    Notes:
6209:    See `MatZeroRowsColumns()` for details on how this routine operates.

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

6213:    In Fortran idxm and idxn should be declared as
6214: $     MatStencil idxm(4,m)
6215:    and the values inserted using
6216: $    idxm(MatStencil_i,1) = i
6217: $    idxm(MatStencil_j,1) = j
6218: $    idxm(MatStencil_k,1) = k
6219: $    idxm(MatStencil_c,1) = c
6220:    etc

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

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

6230:    Level: intermediate

6232: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6233:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6234: @*/
6235: PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6236: {
6237:   PetscInt  dim    = mat->stencil.dim;
6238:   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6239:   PetscInt *dims   = mat->stencil.dims + 1;
6240:   PetscInt *starts = mat->stencil.starts;
6241:   PetscInt *dxm    = (PetscInt *)rows;
6242:   PetscInt *jdxm, i, j, tmp, numNewRows = 0;


6248:   PetscMalloc1(numRows, &jdxm);
6249:   for (i = 0; i < numRows; ++i) {
6250:     /* Skip unused dimensions (they are ordered k, j, i, c) */
6251:     for (j = 0; j < 3 - sdim; ++j) dxm++;
6252:     /* Local index in X dir */
6253:     tmp = *dxm++ - starts[0];
6254:     /* Loop over remaining dimensions */
6255:     for (j = 0; j < dim - 1; ++j) {
6256:       /* If nonlocal, set index to be negative */
6257:       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6258:       /* Update local index */
6259:       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6260:     }
6261:     /* Skip component slot if necessary */
6262:     if (mat->stencil.noc) dxm++;
6263:     /* Local row number */
6264:     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6265:   }
6266:   MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b);
6267:   PetscFree(jdxm);
6268:   return 0;
6269: }

6271: /*@C
6272:    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6273:    of a set of rows of a matrix; using local numbering of rows.

6275:    Collective on mat

6277:    Input Parameters:
6278: +  mat - the matrix
6279: .  numRows - the number of rows to remove
6280: .  rows - the local row indices
6281: .  diag - value put in all diagonals of eliminated rows
6282: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6283: -  b - optional vector of right hand side, that will be adjusted by provided solution

6285:    Notes:
6286:    Before calling `MatZeroRowsLocal()`, the user must first set the
6287:    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.

6289:    See `MatZeroRows()` for details on how this routine operates.

6291:    Level: intermediate

6293: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6294:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6295: @*/
6296: PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6297: {
6303:   MatCheckPreallocated(mat, 1);

6305:   if (mat->ops->zerorowslocal) {
6306:     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6307:   } else {
6308:     IS              is, newis;
6309:     const PetscInt *newRows;

6312:     ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6313:     ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis);
6314:     ISGetIndices(newis, &newRows);
6315:     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6316:     ISRestoreIndices(newis, &newRows);
6317:     ISDestroy(&newis);
6318:     ISDestroy(&is);
6319:   }
6320:   PetscObjectStateIncrease((PetscObject)mat);
6321:   return 0;
6322: }

6324: /*@
6325:    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6326:    of a set of rows of a matrix; using local numbering of rows.

6328:    Collective on mat

6330:    Input Parameters:
6331: +  mat - the matrix
6332: .  is - index set of rows to remove
6333: .  diag - value put in all diagonals of eliminated rows
6334: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6335: -  b - optional vector of right hand side, that will be adjusted by provided solution

6337:    Notes:
6338:    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6339:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6341:    See `MatZeroRows()` for details on how this routine operates.

6343:    Level: intermediate

6345: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6346:           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6347: @*/
6348: PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6349: {
6350:   PetscInt        numRows;
6351:   const PetscInt *rows;

6358:   MatCheckPreallocated(mat, 1);

6360:   ISGetLocalSize(is, &numRows);
6361:   ISGetIndices(is, &rows);
6362:   MatZeroRowsLocal(mat, numRows, rows, diag, x, b);
6363:   ISRestoreIndices(is, &rows);
6364:   return 0;
6365: }

6367: /*@
6368:    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6369:    of a set of rows and columns of a matrix; using local numbering of rows.

6371:    Collective on mat

6373:    Input Parameters:
6374: +  mat - the matrix
6375: .  numRows - the number of rows to remove
6376: .  rows - the global row indices
6377: .  diag - value put in all diagonals of eliminated rows
6378: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6379: -  b - optional vector of right hand side, that will be adjusted by provided solution

6381:    Notes:
6382:    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6383:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6385:    See `MatZeroRowsColumns()` for details on how this routine operates.

6387:    Level: intermediate

6389: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6390:           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6391: @*/
6392: PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6393: {
6394:   IS              is, newis;
6395:   const PetscInt *newRows;

6402:   MatCheckPreallocated(mat, 1);

6405:   ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is);
6406:   ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis);
6407:   ISGetIndices(newis, &newRows);
6408:   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6409:   ISRestoreIndices(newis, &newRows);
6410:   ISDestroy(&newis);
6411:   ISDestroy(&is);
6412:   PetscObjectStateIncrease((PetscObject)mat);
6413:   return 0;
6414: }

6416: /*@
6417:    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6418:    of a set of rows and columns of a matrix; using local numbering of rows.

6420:    Collective on Mat

6422:    Input Parameters:
6423: +  mat - the matrix
6424: .  is - index set of rows to remove
6425: .  diag - value put in all diagonals of eliminated rows
6426: .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6427: -  b - optional vector of right hand side, that will be adjusted by provided solution

6429:    Notes:
6430:    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6431:    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.

6433:    See `MatZeroRowsColumns()` for details on how this routine operates.

6435:    Level: intermediate

6437: .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6438:           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6439: @*/
6440: PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6441: {
6442:   PetscInt        numRows;
6443:   const PetscInt *rows;

6450:   MatCheckPreallocated(mat, 1);

6452:   ISGetLocalSize(is, &numRows);
6453:   ISGetIndices(is, &rows);
6454:   MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b);
6455:   ISRestoreIndices(is, &rows);
6456:   return 0;
6457: }

6459: /*@C
6460:    MatGetSize - Returns the numbers of rows and columns in a matrix.

6462:    Not Collective

6464:    Input Parameter:
6465: .  mat - the matrix

6467:    Output Parameters:
6468: +  m - the number of global rows
6469: -  n - the number of global columns

6471:    Note: both output parameters can be NULL on input.

6473:    Level: beginner

6475: .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6476: @*/
6477: PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6478: {
6480:   if (m) *m = mat->rmap->N;
6481:   if (n) *n = mat->cmap->N;
6482:   return 0;
6483: }

6485: /*@C
6486:    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6487:    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.

6489:    Not Collective

6491:    Input Parameter:
6492: .  mat - the matrix

6494:    Output Parameters:
6495: +  m - the number of local rows, use `NULL` to not obtain this value
6496: -  n - the number of local columns, use `NULL` to not obtain this value

6498:    Level: beginner

6500: .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6501: @*/
6502: PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6503: {
6507:   if (m) *m = mat->rmap->n;
6508:   if (n) *n = mat->cmap->n;
6509:   return 0;
6510: }

6512: /*@C
6513:    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6514:    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.

6516:    Not Collective, unless matrix has not been allocated, then collective on mat

6518:    Input Parameter:
6519: .  mat - the matrix

6521:    Output Parameters:
6522: +  m - the global index of the first local column, use `NULL` to not obtain this value
6523: -  n - one more than the global index of the last local column, use `NULL` to not obtain this value

6525:    Level: developer

6527: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6528: @*/
6529: PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6530: {
6535:   MatCheckPreallocated(mat, 1);
6536:   if (m) *m = mat->cmap->rstart;
6537:   if (n) *n = mat->cmap->rend;
6538:   return 0;
6539: }

6541: /*@C
6542:    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6543:    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
6544:    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts

6546:    Not Collective

6548:    Input Parameter:
6549: .  mat - the matrix

6551:    Output Parameters:
6552: +  m - the global index of the first local row, use `NULL` to not obtain this value
6553: -  n - one more than the global index of the last local row, use `NULL` to not obtain this value

6555:    Note:
6556:   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6557:   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6558:   and then `MPI_Scan()` to calculate prefix sums of the local sizes.

6560:    Level: beginner

6562: .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6563:           `PetscLayout`
6564: @*/
6565: PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6566: {
6571:   MatCheckPreallocated(mat, 1);
6572:   if (m) *m = mat->rmap->rstart;
6573:   if (n) *n = mat->rmap->rend;
6574:   return 0;
6575: }

6577: /*@C
6578:    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6579:    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
6580:    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts

6582:    Not Collective, unless matrix has not been allocated, then collective on mat

6584:    Input Parameters:
6585: .  mat - the matrix

6587:    Output Parameters:
6588: .  ranges - start of each processors portion plus one more than the total length at the end

6590:    Level: beginner

6592: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6593: @*/
6594: PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6595: {
6598:   MatCheckPreallocated(mat, 1);
6599:   PetscLayoutGetRanges(mat->rmap, ranges);
6600:   return 0;
6601: }

6603: /*@C
6604:    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6605:    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.

6607:    Not Collective, unless matrix has not been allocated, then collective on Mat

6609:    Input Parameters:
6610: .  mat - the matrix

6612:    Output Parameters:
6613: .  ranges - start of each processors portion plus one more then the total length at the end

6615:    Level: beginner

6617: .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6618: @*/
6619: PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6620: {
6623:   MatCheckPreallocated(mat, 1);
6624:   PetscLayoutGetRanges(mat->cmap, ranges);
6625:   return 0;
6626: }

6628: /*@C
6629:    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6630:    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6631:    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.

6633:    Not Collective

6635:    Input Parameter:
6636: .  A - matrix

6638:    Output Parameters:
6639: +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6640: -  cols - columns in which this process owns elements, use `NULL` to not obtain this value

6642:    Level: intermediate

6644: .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6645: @*/
6646: PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6647: {
6648:   PetscErrorCode (*f)(Mat, IS *, IS *);

6650:   MatCheckPreallocated(A, 1);
6651:   PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f);
6652:   if (f) {
6653:     (*f)(A, rows, cols);
6654:   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6655:     if (rows) ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows);
6656:     if (cols) ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols);
6657:   }
6658:   return 0;
6659: }

6661: /*@C
6662:    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6663:    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6664:    to complete the factorization.

6666:    Collective on fact

6668:    Input Parameters:
6669: +  fact - the factorized matrix obtained with `MatGetFactor()`
6670: .  mat - the matrix
6671: .  row - row permutation
6672: .  column - column permutation
6673: -  info - structure containing
6674: $      levels - number of levels of fill.
6675: $      expected fill - as ratio of original fill.
6676: $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6677:                 missing diagonal entries)

6679:    Output Parameters:
6680: .  fact - new matrix that has been symbolically factored

6682:    Level: developer

6684:    Notes:
6685:    See [Matrix Factorization](sec_matfactor) for additional information.

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

6691:    Uses the definition of level of fill as in Y. Saad, 2003

6693:    Developer Note:
6694:    The Fortran interface is not autogenerated as the f90
6695:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

6697:    References:
6698: .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003

6700: .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6701:           `MatGetOrdering()`, `MatFactorInfo`
6702: @*/
6703: PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6704: {
6713:   if (!fact->ops->ilufactorsymbolic) {
6714:     MatSolverType stype;
6715:     MatFactorGetSolverType(fact, &stype);
6716:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6717:   }
6720:   MatCheckPreallocated(mat, 2);

6722:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0);
6723:   (fact->ops->ilufactorsymbolic)(fact, mat, row, col, info);
6724:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0);
6725:   return 0;
6726: }

6728: /*@C
6729:    MatICCFactorSymbolic - Performs symbolic incomplete
6730:    Cholesky factorization for a symmetric matrix.  Use
6731:    `MatCholeskyFactorNumeric()` to complete the factorization.

6733:    Collective on fact

6735:    Input Parameters:
6736: +  fact - the factorized matrix obtained with `MatGetFactor()`
6737: .  mat - the matrix to be factored
6738: .  perm - row and column permutation
6739: -  info - structure containing
6740: $      levels - number of levels of fill.
6741: $      expected fill - as ratio of original fill.

6743:    Output Parameter:
6744: .  fact - the factored matrix

6746:    Level: developer

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

6753:    This uses the definition of level of fill as in Y. Saad, 2003

6755:    Developer Note:
6756:    The Fortran interface is not autogenerated as the f90
6757:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

6759:    References:
6760: .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003

6762: .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6763: @*/
6764: PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6765: {
6774:   if (!(fact)->ops->iccfactorsymbolic) {
6775:     MatSolverType stype;
6776:     MatFactorGetSolverType(fact, &stype);
6777:     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6778:   }
6780:   MatCheckPreallocated(mat, 2);

6782:   if (!fact->trivialsymbolic) PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6783:   (fact->ops->iccfactorsymbolic)(fact, mat, perm, info);
6784:   if (!fact->trivialsymbolic) PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0);
6785:   return 0;
6786: }

6788: /*@C
6789:    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6790:    points to an array of valid matrices, they may be reused to store the new
6791:    submatrices.

6793:    Collective on mat

6795:    Input Parameters:
6796: +  mat - the matrix
6797: .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6798: .  irow, icol - index sets of rows and columns to extract
6799: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

6801:    Output Parameter:
6802: .  submat - the array of submatrices

6804:    Notes:
6805:    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6806:    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6807:    to extract a parallel submatrix.

6809:    Some matrix types place restrictions on the row and column
6810:    indices, such as that they be sorted or that they be equal to each other.

6812:    The index sets may not have duplicate entries.

6814:    When extracting submatrices from a parallel matrix, each processor can
6815:    form a different submatrix by setting the rows and columns of its
6816:    individual index sets according to the local submatrix desired.

6818:    When finished using the submatrices, the user should destroy
6819:    them with `MatDestroySubMatrices()`.

6821:    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6822:    original matrix has not changed from that last call to `MatCreateSubMatrices()`.

6824:    This routine creates the matrices in submat; you should NOT create them before
6825:    calling it. It also allocates the array of matrix pointers submat.

6827:    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6828:    request one row/column in a block, they must request all rows/columns that are in
6829:    that block. For example, if the block size is 2 you cannot request just row 0 and
6830:    column 0.

6832:    Fortran Note:
6833:    The Fortran interface is slightly different from that given below; it
6834:    requires one to pass in  as submat a `Mat` (integer) array of size at least n+1.

6836:    Level: advanced

6838: .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6839: @*/
6840: PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6841: {
6842:   PetscInt  i;
6843:   PetscBool eq;

6847:   if (n) {
6852:   }
6854:   if (n && scall == MAT_REUSE_MATRIX) {
6857:   }
6860:   MatCheckPreallocated(mat, 1);
6861:   PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6862:   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6863:   PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6864:   for (i = 0; i < n; i++) {
6865:     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6866:     ISEqualUnsorted(irow[i], icol[i], &eq);
6867:     if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6868: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
6869:     if (mat->boundtocpu && mat->bindingpropagates) {
6870:       MatBindToCPU((*submat)[i], PETSC_TRUE);
6871:       MatSetBindingPropagates((*submat)[i], PETSC_TRUE);
6872:     }
6873: #endif
6874:   }
6875:   return 0;
6876: }

6878: /*@C
6879:    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).

6881:    Collective on mat

6883:    Input Parameters:
6884: +  mat - the matrix
6885: .  n   - the number of submatrixes to be extracted
6886: .  irow, icol - index sets of rows and columns to extract
6887: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

6889:    Output Parameter:
6890: .  submat - the array of submatrices

6892:    Level: advanced

6894:    Note:
6895:    This is used by `PCGASM`

6897: .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6898: @*/
6899: PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6900: {
6901:   PetscInt  i;
6902:   PetscBool eq;

6906:   if (n) {
6911:   }
6913:   if (n && scall == MAT_REUSE_MATRIX) {
6916:   }
6919:   MatCheckPreallocated(mat, 1);

6921:   PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0);
6922:   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6923:   PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0);
6924:   for (i = 0; i < n; i++) {
6925:     ISEqualUnsorted(irow[i], icol[i], &eq);
6926:     if (eq) MatPropagateSymmetryOptions(mat, (*submat)[i]);
6927:   }
6928:   return 0;
6929: }

6931: /*@C
6932:    MatDestroyMatrices - Destroys an array of matrices.

6934:    Collective on mat

6936:    Input Parameters:
6937: +  n - the number of local matrices
6938: -  mat - the matrices (note that this is a pointer to the array of matrices)

6940:    Level: advanced

6942:     Note:
6943:     Frees not only the matrices, but also the array that contains the matrices
6944:            In Fortran will not free the array.

6946: .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6947: @*/
6948: PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
6949: {
6950:   PetscInt i;

6952:   if (!*mat) return 0;

6956:   for (i = 0; i < n; i++) MatDestroy(&(*mat)[i]);

6958:   /* memory is allocated even if n = 0 */
6959:   PetscFree(*mat);
6960:   return 0;
6961: }

6963: /*@C
6964:    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.

6966:    Collective on mat

6968:    Input Parameters:
6969: +  n - the number of local matrices
6970: -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
6971:                        sequence of MatCreateSubMatrices())

6973:    Level: advanced

6975:     Note:
6976:     Frees not only the matrices, but also the array that contains the matrices
6977:            In Fortran will not free the array.

6979: .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6980: @*/
6981: PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
6982: {
6983:   Mat mat0;

6985:   if (!*mat) return 0;
6986:   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */

6990:   mat0 = (*mat)[0];
6991:   if (mat0 && mat0->ops->destroysubmatrices) {
6992:     (mat0->ops->destroysubmatrices)(n, mat);
6993:   } else {
6994:     MatDestroyMatrices(n, mat);
6995:   }
6996:   return 0;
6997: }

6999: /*@C
7000:    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process

7002:    Collective on mat

7004:    Input Parameters:
7005: .  mat - the matrix

7007:    Output Parameter:
7008: .  matstruct - the sequential matrix with the nonzero structure of mat

7010:   Level: developer

7012: .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7013: @*/
7014: PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7015: {

7021:   MatCheckPreallocated(mat, 1);

7023:   PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7024:   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7025:   PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0);
7026:   return 0;
7027: }

7029: /*@C
7030:    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.

7032:    Collective on mat

7034:    Input Parameters:
7035: .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7036:                        sequence of `MatGetSequentialNonzeroStructure()`)

7038:    Level: advanced

7040:     Note:
7041:     Frees not only the matrices, but also the array that contains the matrices

7043: .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7044: @*/
7045: PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7046: {
7048:   MatDestroy(mat);
7049:   return 0;
7050: }

7052: /*@
7053:    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7054:    replaces the index sets by larger ones that represent submatrices with
7055:    additional overlap.

7057:    Collective on mat

7059:    Input Parameters:
7060: +  mat - the matrix
7061: .  n   - the number of index sets
7062: .  is  - the array of index sets (these index sets will changed during the call)
7063: -  ov  - the additional overlap requested

7065:    Options Database:
7066: .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)

7068:    Level: developer

7070:    Developer Note:
7071:    Any implementation must preserve block sizes. That is: if the row block size and the column block size of mat are equal to bs, then the output index sets must be compatible with bs.

7073: .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7074: @*/
7075: PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7076: {
7077:   PetscInt i, bs, cbs;

7083:   if (n) {
7086:   }
7089:   MatCheckPreallocated(mat, 1);

7091:   if (!ov || !n) return 0;
7092:   PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7093:   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7094:   PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7095:   MatGetBlockSizes(mat, &bs, &cbs);
7096:   if (bs == cbs) {
7097:     for (i = 0; i < n; i++) ISSetBlockSize(is[i], bs);
7098:   }
7099:   return 0;
7100: }

7102: PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);

7104: /*@
7105:    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7106:    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7107:    additional overlap.

7109:    Collective on mat

7111:    Input Parameters:
7112: +  mat - the matrix
7113: .  n   - the number of index sets
7114: .  is  - the array of index sets (these index sets will changed during the call)
7115: -  ov  - the additional overlap requested

7117: `   Options Database:
7118: .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)

7120:    Level: developer

7122: .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7123: @*/
7124: PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7125: {
7126:   PetscInt i;

7131:   if (n) {
7134:   }
7137:   MatCheckPreallocated(mat, 1);
7138:   if (!ov) return 0;
7139:   PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0);
7140:   for (i = 0; i < n; i++) MatIncreaseOverlapSplit_Single(mat, &is[i], ov);
7141:   PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0);
7142:   return 0;
7143: }

7145: /*@
7146:    MatGetBlockSize - Returns the matrix block size.

7148:    Not Collective

7150:    Input Parameter:
7151: .  mat - the matrix

7153:    Output Parameter:
7154: .  bs - block size

7156:    Notes:
7157:     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.

7159:    If the block size has not been set yet this routine returns 1.

7161:    Level: intermediate

7163: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7164: @*/
7165: PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7166: {
7169:   *bs = PetscAbs(mat->rmap->bs);
7170:   return 0;
7171: }

7173: /*@
7174:    MatGetBlockSizes - Returns the matrix block row and column sizes.

7176:    Not Collective

7178:    Input Parameter:
7179: .  mat - the matrix

7181:    Output Parameters:
7182: +  rbs - row block size
7183: -  cbs - column block size

7185:    Notes:
7186:     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7187:     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.

7189:    If a block size has not been set yet this routine returns 1.

7191:    Level: intermediate

7193: .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7194: @*/
7195: PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7196: {
7200:   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7201:   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7202:   return 0;
7203: }

7205: /*@
7206:    MatSetBlockSize - Sets the matrix block size.

7208:    Logically Collective on mat

7210:    Input Parameters:
7211: +  mat - the matrix
7212: -  bs - block size

7214:    Notes:
7215:     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7216:     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.

7218:     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7219:     is compatible with the matrix local sizes.

7221:    Level: intermediate

7223: .seealso:  `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7224: @*/
7225: PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7226: {
7229:   MatSetBlockSizes(mat, bs, bs);
7230:   return 0;
7231: }

7233: typedef struct {
7234:   PetscInt         n;
7235:   IS              *is;
7236:   Mat             *mat;
7237:   PetscObjectState nonzerostate;
7238:   Mat              C;
7239: } EnvelopeData;

7241: static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7242: {
7243:   for (PetscInt i = 0; i < edata->n; i++) ISDestroy(&edata->is[i]);
7244:   PetscFree(edata->is);
7245:   PetscFree(edata);
7246:   return 0;
7247: }

7249: /*
7250:    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7251:          the sizes of these blocks in the matrix. An individual block may lie over several processes.

7253:    Collective on mat

7255:    Input Parameter:
7256: .  mat - the matrix

7258:    Notes:
7259:      There can be zeros within the blocks

7261:      The blocks can overlap between processes, including laying on more than two processes

7263: .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7264: */
7265: static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7266: {
7267:   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7268:   PetscInt          *diag, *odiag, sc;
7269:   VecScatter         scatter;
7270:   PetscScalar       *seqv;
7271:   const PetscScalar *parv;
7272:   const PetscInt    *ia, *ja;
7273:   PetscBool          set, flag, done;
7274:   Mat                AA = mat, A;
7275:   MPI_Comm           comm;
7276:   PetscMPIInt        rank, size, tag;
7277:   MPI_Status         status;
7278:   PetscContainer     container;
7279:   EnvelopeData      *edata;
7280:   Vec                seq, par;
7281:   IS                 isglobal;

7284:   MatIsSymmetricKnown(mat, &set, &flag);
7285:   if (!set || !flag) {
7286:     /* TOO: only needs nonzero structure of transpose */
7287:     MatTranspose(mat, MAT_INITIAL_MATRIX, &AA);
7288:     MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN);
7289:   }
7290:   MatAIJGetLocalMat(AA, &A);
7291:   MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);

7294:   MatGetLocalSize(mat, &n, NULL);
7295:   PetscObjectGetNewTag((PetscObject)mat, &tag);
7296:   PetscObjectGetComm((PetscObject)mat, &comm);
7297:   MPI_Comm_size(comm, &size);
7298:   MPI_Comm_rank(comm, &rank);

7300:   PetscMalloc2(n, &sizes, n, &starts);

7302:   if (rank > 0) {
7303:     MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status);
7304:     MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status);
7305:   }
7306:   MatGetOwnershipRange(mat, &rstart, NULL);
7307:   for (i = 0; i < n; i++) {
7308:     env = PetscMax(env, ja[ia[i + 1] - 1]);
7309:     II  = rstart + i;
7310:     if (env == II) {
7311:       starts[lblocks]  = tbs;
7312:       sizes[lblocks++] = 1 + II - tbs;
7313:       tbs              = 1 + II;
7314:     }
7315:   }
7316:   if (rank < size - 1) {
7317:     MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm);
7318:     MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm);
7319:   }

7321:   MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done);
7322:   if (!set || !flag) MatDestroy(&AA);
7323:   MatDestroy(&A);

7325:   PetscNew(&edata);
7326:   MatGetNonzeroState(mat, &edata->nonzerostate);
7327:   edata->n = lblocks;
7328:   /* create IS needed for extracting blocks from the original matrix */
7329:   PetscMalloc1(lblocks, &edata->is);
7330:   for (PetscInt i = 0; i < lblocks; i++) ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]);

7332:   /* Create the resulting inverse matrix structure with preallocation information */
7333:   MatCreate(PetscObjectComm((PetscObject)mat), &edata->C);
7334:   MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N);
7335:   MatSetBlockSizesFromMats(edata->C, mat, mat);
7336:   MatSetType(edata->C, MATAIJ);

7338:   /* Communicate the start and end of each row, from each block to the correct rank */
7339:   /* TODO: Use PetscSF instead of VecScatter */
7340:   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7341:   VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq);
7342:   VecGetArrayWrite(seq, &seqv);
7343:   for (PetscInt i = 0; i < lblocks; i++) {
7344:     for (PetscInt j = 0; j < sizes[i]; j++) {
7345:       seqv[cnt]     = starts[i];
7346:       seqv[cnt + 1] = starts[i] + sizes[i];
7347:       cnt += 2;
7348:     }
7349:   }
7350:   VecRestoreArrayWrite(seq, &seqv);
7351:   MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat));
7352:   sc -= cnt;
7353:   VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par);
7354:   ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal);
7355:   VecScatterCreate(seq, NULL, par, isglobal, &scatter);
7356:   ISDestroy(&isglobal);
7357:   VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7358:   VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD);
7359:   VecScatterDestroy(&scatter);
7360:   VecDestroy(&seq);
7361:   MatGetOwnershipRangeColumn(mat, &cstart, &cend);
7362:   PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag);
7363:   VecGetArrayRead(par, &parv);
7364:   cnt = 0;
7365:   MatGetSize(mat, NULL, &n);
7366:   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7367:     PetscInt start, end, d = 0, od = 0;

7369:     start = (PetscInt)PetscRealPart(parv[cnt]);
7370:     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7371:     cnt += 2;

7373:     if (start < cstart) {
7374:       od += cstart - start + n - cend;
7375:       d += cend - cstart;
7376:     } else if (start < cend) {
7377:       od += n - cend;
7378:       d += cend - start;
7379:     } else od += n - start;
7380:     if (end <= cstart) {
7381:       od -= cstart - end + n - cend;
7382:       d -= cend - cstart;
7383:     } else if (end < cend) {
7384:       od -= n - cend;
7385:       d -= cend - end;
7386:     } else od -= n - end;

7388:     odiag[i] = od;
7389:     diag[i]  = d;
7390:   }
7391:   VecRestoreArrayRead(par, &parv);
7392:   VecDestroy(&par);
7393:   MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL);
7394:   PetscFree2(diag, odiag);
7395:   PetscFree2(sizes, starts);

7397:   PetscContainerCreate(PETSC_COMM_SELF, &container);
7398:   PetscContainerSetPointer(container, edata);
7399:   PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy);
7400:   PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container);
7401:   PetscObjectDereference((PetscObject)container);
7402:   return 0;
7403: }

7405: /*@
7406:   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A

7408:   Collective on A

7410:   Input Parameters:
7411: . A - the matrix

7413:   Output Parameters:
7414: . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.

7416:   Note:
7417:      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.

7419:   Level: advanced

7421: .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7422: @*/
7423: PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7424: {
7425:   PetscContainer   container;
7426:   EnvelopeData    *edata;
7427:   PetscObjectState nonzerostate;

7429:   PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7430:   if (!container) {
7431:     MatComputeVariableBlockEnvelope(A);
7432:     PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container);
7433:   }
7434:   PetscContainerGetPointer(container, (void **)&edata);
7435:   MatGetNonzeroState(A, &nonzerostate);

7439:   MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat);
7440:   *C = edata->C;

7442:   for (PetscInt i = 0; i < edata->n; i++) {
7443:     Mat          D;
7444:     PetscScalar *dvalues;

7446:     MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D);
7447:     MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE);
7448:     MatSeqDenseInvert(D);
7449:     MatDenseGetArray(D, &dvalues);
7450:     MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES);
7451:     MatDestroy(&D);
7452:   }
7453:   MatDestroySubMatrices(edata->n, &edata->mat);
7454:   MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY);
7455:   MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY);
7456:   return 0;
7457: }

7459: /*@
7460:    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size

7462:    Logically Collective on mat

7464:    Input Parameters:
7465: +  mat - the matrix
7466: .  nblocks - the number of blocks on this process, each block can only exist on a single process
7467: -  bsizes - the block sizes

7469:    Notes:
7470:     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices

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

7474:    Level: intermediate

7476: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7477:           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7478: @*/
7479: PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7480: {
7481:   PetscInt i, ncnt = 0, nlocal;

7485:   MatGetLocalSize(mat, &nlocal, NULL);
7486:   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7488:   PetscFree(mat->bsizes);
7489:   mat->nblocks = nblocks;
7490:   PetscMalloc1(nblocks, &mat->bsizes);
7491:   PetscArraycpy(mat->bsizes, bsizes, nblocks);
7492:   return 0;
7493: }

7495: /*@C
7496:    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size

7498:    Logically Collective on mat

7500:    Input Parameter:
7501: .  mat - the matrix

7503:    Output Parameters:
7504: +  nblocks - the number of blocks on this process
7505: -  bsizes - the block sizes

7507:    Fortran Note:
7508:    Currently not supported from Fortran

7510:    Level: intermediate

7512: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7513: @*/
7514: PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7515: {
7517:   *nblocks = mat->nblocks;
7518:   *bsizes  = mat->bsizes;
7519:   return 0;
7520: }

7522: /*@
7523:    MatSetBlockSizes - Sets the matrix block row and column sizes.

7525:    Logically Collective on mat

7527:    Input Parameters:
7528: +  mat - the matrix
7529: .  rbs - row block size
7530: -  cbs - column block size

7532:    Notes:
7533:     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7534:     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7535:     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.

7537:     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7538:     are compatible with the matrix local sizes.

7540:     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.

7542:    Level: intermediate

7544: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7545: @*/
7546: PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7547: {
7551:   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7552:   if (mat->rmap->refcnt) {
7553:     ISLocalToGlobalMapping l2g  = NULL;
7554:     PetscLayout            nmap = NULL;

7556:     PetscLayoutDuplicate(mat->rmap, &nmap);
7557:     if (mat->rmap->mapping) ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g);
7558:     PetscLayoutDestroy(&mat->rmap);
7559:     mat->rmap          = nmap;
7560:     mat->rmap->mapping = l2g;
7561:   }
7562:   if (mat->cmap->refcnt) {
7563:     ISLocalToGlobalMapping l2g  = NULL;
7564:     PetscLayout            nmap = NULL;

7566:     PetscLayoutDuplicate(mat->cmap, &nmap);
7567:     if (mat->cmap->mapping) ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g);
7568:     PetscLayoutDestroy(&mat->cmap);
7569:     mat->cmap          = nmap;
7570:     mat->cmap->mapping = l2g;
7571:   }
7572:   PetscLayoutSetBlockSize(mat->rmap, rbs);
7573:   PetscLayoutSetBlockSize(mat->cmap, cbs);
7574:   return 0;
7575: }

7577: /*@
7578:    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices

7580:    Logically Collective on mat

7582:    Input Parameters:
7583: +  mat - the matrix
7584: .  fromRow - matrix from which to copy row block size
7585: -  fromCol - matrix from which to copy column block size (can be same as fromRow)

7587:    Level: developer

7589: .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7590: @*/
7591: PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7592: {
7596:   if (fromRow->rmap->bs > 0) PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs);
7597:   if (fromCol->cmap->bs > 0) PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs);
7598:   return 0;
7599: }

7601: /*@
7602:    MatResidual - Default routine to calculate the residual r = b - Ax

7604:    Collective on mat

7606:    Input Parameters:
7607: +  mat - the matrix
7608: .  b   - the right-hand-side
7609: -  x   - the approximate solution

7611:    Output Parameter:
7612: .  r - location to store the residual

7614:    Level: developer

7616: .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7617: @*/
7618: PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7619: {
7625:   MatCheckPreallocated(mat, 1);
7626:   PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0);
7627:   if (!mat->ops->residual) {
7628:     MatMult(mat, x, r);
7629:     VecAYPX(r, -1.0, b);
7630:   } else {
7631:     PetscUseTypeMethod(mat, residual, b, x, r);
7632:   }
7633:   PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0);
7634:   return 0;
7635: }

7637: /*@C
7638:     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix

7640:    Collective on mat

7642:     Input Parameters:
7643: +   mat - the matrix
7644: .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7645: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7646: -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7647:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7648:                  always used.

7650:     Output Parameters:
7651: +   n - number of local rows in the (possibly compressed) matrix, use NULL if not needed
7652: .   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
7653: .   ja - the column indices, use NULL if not needed
7654: -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7655:            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set

7657:     Level: developer

7659:     Notes:
7660:     You CANNOT change any of the ia[] or ja[] values.

7662:     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.

7664:     Fortran Notes:
7665:     In Fortran use
7666: $
7667: $      PetscInt ia(1), ja(1)
7668: $      PetscOffset iia, jja
7669: $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7670: $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)

7672:      or
7673: $
7674: $    PetscInt, pointer :: ia(:),ja(:)
7675: $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7676: $    ! Access the ith and jth entries via ia(i) and ja(j)

7678: .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7679: @*/
7680: PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7681: {
7688:   MatCheckPreallocated(mat, 1);
7689:   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7690:   else {
7691:     if (done) *done = PETSC_TRUE;
7692:     PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0);
7693:     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7694:     PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0);
7695:   }
7696:   return 0;
7697: }

7699: /*@C
7700:     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.

7702:     Collective on mat

7704:     Input Parameters:
7705: +   mat - the matrix
7706: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7707: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7708:                 symmetrized
7709: .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7710:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7711:                  always used.
7712: .   n - number of columns in the (possibly compressed) matrix
7713: .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7714: -   ja - the row indices

7716:     Output Parameters:
7717: .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned

7719:     Level: developer

7721: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7722: @*/
7723: PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7724: {
7731:   MatCheckPreallocated(mat, 1);
7732:   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7733:   else {
7734:     *done = PETSC_TRUE;
7735:     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7736:   }
7737:   return 0;
7738: }

7740: /*@C
7741:     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.

7743:     Collective on mat

7745:     Input Parameters:
7746: +   mat - the matrix
7747: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7748: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7749: .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7750:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7751:                  always used.
7752: .   n - size of (possibly compressed) matrix
7753: .   ia - the row pointers
7754: -   ja - the column indices

7756:     Output Parameters:
7757: .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned

7759:     Note:
7760:     This routine zeros out n, ia, and ja. This is to prevent accidental
7761:     us of the array after it has been restored. If you pass NULL, it will
7762:     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.

7764:     Level: developer

7766: .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7767: @*/
7768: PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7769: {
7775:   MatCheckPreallocated(mat, 1);

7777:   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7778:   else {
7779:     if (done) *done = PETSC_TRUE;
7780:     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7781:     if (n) *n = 0;
7782:     if (ia) *ia = NULL;
7783:     if (ja) *ja = NULL;
7784:   }
7785:   return 0;
7786: }

7788: /*@C
7789:     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.

7791:     Collective on Mat

7793:     Input Parameters:
7794: +   mat - the matrix
7795: .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7796: .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7797: -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7798:                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7799:                  always used.

7801:     Output Parameters:
7802: +   n - size of (possibly compressed) matrix
7803: .   ia - the column pointers
7804: .   ja - the row indices
7805: -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned

7807:     Level: developer

7809: .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7810: @*/
7811: PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7812: {
7818:   MatCheckPreallocated(mat, 1);

7820:   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7821:   else {
7822:     *done = PETSC_TRUE;
7823:     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7824:     if (n) *n = 0;
7825:     if (ia) *ia = NULL;
7826:     if (ja) *ja = NULL;
7827:   }
7828:   return 0;
7829: }

7831: /*@C
7832:     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.

7834:     Collective on mat

7836:     Input Parameters:
7837: +   mat - the matrix
7838: .   ncolors - max color value
7839: .   n   - number of entries in colorarray
7840: -   colorarray - array indicating color for each column

7842:     Output Parameters:
7843: .   iscoloring - coloring generated using colorarray information

7845:     Level: developer

7847: .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7848: @*/
7849: PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
7850: {
7855:   MatCheckPreallocated(mat, 1);

7857:   if (!mat->ops->coloringpatch) {
7858:     ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring);
7859:   } else {
7860:     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7861:   }
7862:   return 0;
7863: }

7865: /*@
7866:    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.

7868:    Logically Collective on mat

7870:    Input Parameter:
7871: .  mat - the factored matrix to be reset

7873:    Notes:
7874:    This routine should be used only with factored matrices formed by in-place
7875:    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
7876:    format).  This option can save memory, for example, when solving nonlinear
7877:    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7878:    ILU(0) preconditioner.

7880:    Note that one can specify in-place ILU(0) factorization by calling
7881: .vb
7882:      PCType(pc,PCILU);
7883:      PCFactorSeUseInPlace(pc);
7884: .ve
7885:    or by using the options -pc_type ilu -pc_factor_in_place

7887:    In-place factorization ILU(0) can also be used as a local
7888:    solver for the blocks within the block Jacobi or additive Schwarz
7889:    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
7890:    for details on setting local solver options.

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

7896:    Level: developer

7898: .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7899: @*/
7900: PetscErrorCode MatSetUnfactored(Mat mat)
7901: {
7904:   MatCheckPreallocated(mat, 1);
7905:   mat->factortype = MAT_FACTOR_NONE;
7906:   if (!mat->ops->setunfactored) return 0;
7907:   PetscUseTypeMethod(mat, setunfactored);
7908:   return 0;
7909: }

7911: /*MC
7912:     MatDenseGetArrayF90 - Accesses a matrix array from Fortran

7914:     Synopsis:
7915:     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)

7917:     Not collective

7919:     Input Parameter:
7920: .   x - matrix

7922:     Output Parameters:
7923: +   xx_v - the Fortran pointer to the array
7924: -   ierr - error code

7926:     Example of Usage:
7927: .vb
7928:       PetscScalar, pointer xx_v(:,:)
7929:       ....
7930:       call MatDenseGetArrayF90(x,xx_v,ierr)
7931:       a = xx_v(3)
7932:       call MatDenseRestoreArrayF90(x,xx_v,ierr)
7933: .ve

7935:     Level: advanced

7937: .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`

7939: M*/

7941: /*MC
7942:     MatDenseRestoreArrayF90 - Restores a matrix array that has been
7943:     accessed with `MatDenseGetArrayF90()`.

7945:     Synopsis:
7946:     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)

7948:     Not collective

7950:     Input Parameters:
7951: +   x - matrix
7952: -   xx_v - the Fortran90 pointer to the array

7954:     Output Parameter:
7955: .   ierr - error code

7957:     Example of Usage:
7958: .vb
7959:        PetscScalar, pointer xx_v(:,:)
7960:        ....
7961:        call MatDenseGetArrayF90(x,xx_v,ierr)
7962:        a = xx_v(3)
7963:        call MatDenseRestoreArrayF90(x,xx_v,ierr)
7964: .ve

7966:     Level: advanced

7968: .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`

7970: M*/

7972: /*MC
7973:     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.

7975:     Synopsis:
7976:     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)

7978:     Not collective

7980:     Input Parameter:
7981: .   x - matrix

7983:     Output Parameters:
7984: +   xx_v - the Fortran pointer to the array
7985: -   ierr - error code

7987:     Example of Usage:
7988: .vb
7989:       PetscScalar, pointer xx_v(:)
7990:       ....
7991:       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
7992:       a = xx_v(3)
7993:       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
7994: .ve

7996:     Level: advanced

7998: .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`

8000: M*/

8002: /*MC
8003:     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8004:     accessed with `MatSeqAIJGetArrayF90()`.

8006:     Synopsis:
8007:     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)

8009:     Not collective

8011:     Input Parameters:
8012: +   x - matrix
8013: -   xx_v - the Fortran90 pointer to the array

8015:     Output Parameter:
8016: .   ierr - error code

8018:     Example of Usage:
8019: .vb
8020:        PetscScalar, pointer xx_v(:)
8021:        ....
8022:        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8023:        a = xx_v(3)
8024:        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8025: .ve

8027:     Level: advanced

8029: .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`

8031: M*/

8033: /*@
8034:     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8035:                       as the original matrix.

8037:     Collective on mat

8039:     Input Parameters:
8040: +   mat - the original matrix
8041: .   isrow - parallel IS containing the rows this processor should obtain
8042: .   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.
8043: -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

8045:     Output Parameter:
8046: .   newmat - the new submatrix, of the same type as the old

8048:     Level: advanced

8050:     Notes:
8051:     The submatrix will be able to be multiplied with vectors using the same layout as iscol.

8053:     Some matrix types place restrictions on the row and column indices, such
8054:     as that they be sorted or that they be equal to each other.

8056:     The index sets may not have duplicate entries.

8058:       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8059:    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8060:    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8061:    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8062:    you are finished using it.

8064:     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8065:     the input matrix.

8067:     If iscol is NULL then all columns are obtained (not supported in Fortran).

8069:    Example usage:
8070:    Consider the following 8x8 matrix with 34 non-zero values, that is
8071:    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8072:    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8073:    as follows:

8075: .vb
8076:             1  2  0  |  0  3  0  |  0  4
8077:     Proc0   0  5  6  |  7  0  0  |  8  0
8078:             9  0 10  | 11  0  0  | 12  0
8079:     -------------------------------------
8080:            13  0 14  | 15 16 17  |  0  0
8081:     Proc1   0 18  0  | 19 20 21  |  0  0
8082:             0  0  0  | 22 23  0  | 24  0
8083:     -------------------------------------
8084:     Proc2  25 26 27  |  0  0 28  | 29  0
8085:            30  0  0  | 31 32 33  |  0 34
8086: .ve

8088:     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is

8090: .vb
8091:             2  0  |  0  3  0  |  0
8092:     Proc0   5  6  |  7  0  0  |  8
8093:     -------------------------------
8094:     Proc1  18  0  | 19 20 21  |  0
8095:     -------------------------------
8096:     Proc2  26 27  |  0  0 28  | 29
8097:             0  0  | 31 32 33  |  0
8098: .ve

8100: .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8101: @*/
8102: PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8103: {
8104:   PetscMPIInt size;
8105:   Mat        *local;
8106:   IS          iscoltmp;
8107:   PetscBool   flg;


8118:   MatCheckPreallocated(mat, 1);
8119:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);

8121:   if (!iscol || isrow == iscol) {
8122:     PetscBool   stride;
8123:     PetscMPIInt grabentirematrix = 0, grab;
8124:     PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride);
8125:     if (stride) {
8126:       PetscInt first, step, n, rstart, rend;
8127:       ISStrideGetInfo(isrow, &first, &step);
8128:       if (step == 1) {
8129:         MatGetOwnershipRange(mat, &rstart, &rend);
8130:         if (rstart == first) {
8131:           ISGetLocalSize(isrow, &n);
8132:           if (n == rend - rstart) grabentirematrix = 1;
8133:         }
8134:       }
8135:     }
8136:     MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat));
8137:     if (grab) {
8138:       PetscInfo(mat, "Getting entire matrix as submatrix\n");
8139:       if (cll == MAT_INITIAL_MATRIX) {
8140:         *newmat = mat;
8141:         PetscObjectReference((PetscObject)mat);
8142:       }
8143:       return 0;
8144:     }
8145:   }

8147:   if (!iscol) {
8148:     ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp);
8149:   } else {
8150:     iscoltmp = iscol;
8151:   }

8153:   /* if original matrix is on just one processor then use submatrix generated */
8154:   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8155:     MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat);
8156:     goto setproperties;
8157:   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8158:     MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local);
8159:     *newmat = *local;
8160:     PetscFree(local);
8161:     goto setproperties;
8162:   } else if (!mat->ops->createsubmatrix) {
8163:     /* Create a new matrix type that implements the operation using the full matrix */
8164:     PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8165:     switch (cll) {
8166:     case MAT_INITIAL_MATRIX:
8167:       MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat);
8168:       break;
8169:     case MAT_REUSE_MATRIX:
8170:       MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp);
8171:       break;
8172:     default:
8173:       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8174:     }
8175:     PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);
8176:     goto setproperties;
8177:   }

8179:   PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0);
8180:   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8181:   PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0);

8183: setproperties:
8184:   ISEqualUnsorted(isrow, iscoltmp, &flg);
8185:   if (flg) MatPropagateSymmetryOptions(mat, *newmat);
8186:   if (!iscol) ISDestroy(&iscoltmp);
8187:   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscObjectStateIncrease((PetscObject)*newmat);
8188:   return 0;
8189: }

8191: /*@
8192:    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix

8194:    Not Collective

8196:    Input Parameters:
8197: +  A - the matrix we wish to propagate options from
8198: -  B - the matrix we wish to propagate options to

8200:    Level: beginner

8202:    Note:
8203:    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`

8205: .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8206: @*/
8207: PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8208: {
8211:   B->symmetry_eternal            = A->symmetry_eternal;
8212:   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8213:   B->symmetric                   = A->symmetric;
8214:   B->structurally_symmetric      = A->structurally_symmetric;
8215:   B->spd                         = A->spd;
8216:   B->hermitian                   = A->hermitian;
8217:   return 0;
8218: }

8220: /*@
8221:    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8222:    used during the assembly process to store values that belong to
8223:    other processors.

8225:    Not Collective

8227:    Input Parameters:
8228: +  mat   - the matrix
8229: .  size  - the initial size of the stash.
8230: -  bsize - the initial size of the block-stash(if used).

8232:    Options Database Keys:
8233: +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8234: -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>

8236:    Level: intermediate

8238:    Notes:
8239:      The block-stash is used for values set with `MatSetValuesBlocked()` while
8240:      the stash is used for values set with `MatSetValues()`

8242:      Run with the option -info and look for output of the form
8243:      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8244:      to determine the appropriate value, MM, to use for size and
8245:      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8246:      to determine the value, BMM to use for bsize

8248: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8249: @*/
8250: PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8251: {
8254:   MatStashSetInitialSize_Private(&mat->stash, size);
8255:   MatStashSetInitialSize_Private(&mat->bstash, bsize);
8256:   return 0;
8257: }

8259: /*@
8260:    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8261:      the matrix

8263:    Neighbor-wise Collective on mat

8265:    Input Parameters:
8266: +  mat   - the matrix
8267: .  x,y - the vectors
8268: -  w - where the result is stored

8270:    Level: intermediate

8272:    Notes:
8273:     w may be the same vector as y.

8275:     This allows one to use either the restriction or interpolation (its transpose)
8276:     matrix to do the interpolation

8278: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8279: @*/
8280: PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8281: {
8282:   PetscInt M, N, Ny;

8288:   MatGetSize(A, &M, &N);
8289:   VecGetSize(y, &Ny);
8290:   if (M == Ny) {
8291:     MatMultAdd(A, x, y, w);
8292:   } else {
8293:     MatMultTransposeAdd(A, x, y, w);
8294:   }
8295:   return 0;
8296: }

8298: /*@
8299:    MatInterpolate - y = A*x or A'*x depending on the shape of
8300:      the matrix

8302:    Neighbor-wise Collective on mat

8304:    Input Parameters:
8305: +  mat   - the matrix
8306: -  x,y - the vectors

8308:    Level: intermediate

8310:    Note:
8311:     This allows one to use either the restriction or interpolation (its transpose)
8312:     matrix to do the interpolation

8314: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8315: @*/
8316: PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8317: {
8318:   PetscInt M, N, Ny;

8323:   MatGetSize(A, &M, &N);
8324:   VecGetSize(y, &Ny);
8325:   if (M == Ny) {
8326:     MatMult(A, x, y);
8327:   } else {
8328:     MatMultTranspose(A, x, y);
8329:   }
8330:   return 0;
8331: }

8333: /*@
8334:    MatRestrict - y = A*x or A'*x

8336:    Neighbor-wise Collective on Mat

8338:    Input Parameters:
8339: +  mat   - the matrix
8340: -  x,y - the vectors

8342:    Level: intermediate

8344:    Note:
8345:     This allows one to use either the restriction or interpolation (its transpose)
8346:     matrix to do the restriction

8348: .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8349: @*/
8350: PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8351: {
8352:   PetscInt M, N, Ny;

8357:   MatGetSize(A, &M, &N);
8358:   VecGetSize(y, &Ny);
8359:   if (M == Ny) {
8360:     MatMult(A, x, y);
8361:   } else {
8362:     MatMultTranspose(A, x, y);
8363:   }
8364:   return 0;
8365: }

8367: /*@
8368:    MatMatInterpolateAdd - Y = W + A*X or W + A'*X

8370:    Neighbor-wise Collective on Mat

8372:    Input Parameters:
8373: +  mat   - the matrix
8374: -  w, x - the input dense matrices

8376:    Output Parameters:
8377: .  y - the output dense matrix

8379:    Level: intermediate

8381:    Note:
8382:     This allows one to use either the restriction or interpolation (its transpose)
8383:     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8384:     otherwise it will be recreated. y must be initialized to NULL if not supplied.

8386: .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8387: @*/
8388: PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8389: {
8390:   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8391:   PetscBool trans = PETSC_TRUE;
8392:   MatReuse  reuse = MAT_INITIAL_MATRIX;

8399:   MatGetSize(A, &M, &N);
8400:   MatGetSize(x, &Mx, &Nx);
8401:   if (N == Mx) trans = PETSC_FALSE;
8403:   Mo = trans ? N : M;
8404:   if (*y) {
8405:     MatGetSize(*y, &My, &Ny);
8406:     if (Mo == My && Nx == Ny) {
8407:       reuse = MAT_REUSE_MATRIX;
8408:     } else {
8410:       MatDestroy(y);
8411:     }
8412:   }

8414:   if (w && *y == w) { /* this is to minimize changes in PCMG */
8415:     PetscBool flg;

8417:     PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w);
8418:     if (w) {
8419:       PetscInt My, Ny, Mw, Nw;

8421:       PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg);
8422:       MatGetSize(*y, &My, &Ny);
8423:       MatGetSize(w, &Mw, &Nw);
8424:       if (!flg || My != Mw || Ny != Nw) w = NULL;
8425:     }
8426:     if (!w) {
8427:       MatDuplicate(*y, MAT_COPY_VALUES, &w);
8428:       PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w);
8429:       PetscObjectDereference((PetscObject)w);
8430:     } else {
8431:       MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN);
8432:     }
8433:   }
8434:   if (!trans) {
8435:     MatMatMult(A, x, reuse, PETSC_DEFAULT, y);
8436:   } else {
8437:     MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y);
8438:   }
8439:   if (w) MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN);
8440:   return 0;
8441: }

8443: /*@
8444:    MatMatInterpolate - Y = A*X or A'*X

8446:    Neighbor-wise Collective on Mat

8448:    Input Parameters:
8449: +  mat   - the matrix
8450: -  x - the input dense matrix

8452:    Output Parameters:
8453: .  y - the output dense matrix

8455:    Level: intermediate

8457:    Note:
8458:     This allows one to use either the restriction or interpolation (its transpose)
8459:     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8460:     otherwise it will be recreated. y must be initialized to NULL if not supplied.

8462: .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8463: @*/
8464: PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8465: {
8466:   MatMatInterpolateAdd(A, x, NULL, y);
8467:   return 0;
8468: }

8470: /*@
8471:    MatMatRestrict - Y = A*X or A'*X

8473:    Neighbor-wise Collective on Mat

8475:    Input Parameters:
8476: +  mat   - the matrix
8477: -  x - the input dense matrix

8479:    Output Parameters:
8480: .  y - the output dense matrix

8482:    Level: intermediate

8484:    Note:
8485:     This allows one to use either the restriction or interpolation (its transpose)
8486:     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8487:     otherwise it will be recreated. y must be initialized to NULL if not supplied.

8489: .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8490: @*/
8491: PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8492: {
8493:   MatMatInterpolateAdd(A, x, NULL, y);
8494:   return 0;
8495: }

8497: /*@
8498:    MatGetNullSpace - retrieves the null space of a matrix.

8500:    Logically Collective on mat

8502:    Input Parameters:
8503: +  mat - the matrix
8504: -  nullsp - the null space object

8506:    Level: developer

8508: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8509: @*/
8510: PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8511: {
8514:   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8515:   return 0;
8516: }

8518: /*@
8519:    MatSetNullSpace - attaches a null space to a matrix.

8521:    Logically Collective on mat

8523:    Input Parameters:
8524: +  mat - the matrix
8525: -  nullsp - the null space object

8527:    Level: advanced

8529:    Notes:
8530:       This null space is used by the `KSP` linear solvers to solve singular systems.

8532:       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

8534:       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
8535:       to zero but the linear system will still be solved in a least squares sense.

8537:       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8538:    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).
8539:    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
8540:    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
8541:    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).
8542:    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.

8544:     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8545:     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8546:     routine also automatically calls `MatSetTransposeNullSpace()`.

8548:     The user should call `MatNullSpaceDestroy()`.

8550: .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8551:           `KSPSetPCSide()`
8552: @*/
8553: PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8554: {
8557:   if (nullsp) PetscObjectReference((PetscObject)nullsp);
8558:   MatNullSpaceDestroy(&mat->nullsp);
8559:   mat->nullsp = nullsp;
8560:   if (mat->symmetric == PETSC_BOOL3_TRUE) MatSetTransposeNullSpace(mat, nullsp);
8561:   return 0;
8562: }

8564: /*@
8565:    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.

8567:    Logically Collective on mat

8569:    Input Parameters:
8570: +  mat - the matrix
8571: -  nullsp - the null space object

8573:    Level: developer

8575: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8576: @*/
8577: PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8578: {
8582:   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8583:   return 0;
8584: }

8586: /*@
8587:    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix

8589:    Logically Collective on mat

8591:    Input Parameters:
8592: +  mat - the matrix
8593: -  nullsp - the null space object

8595:    Level: advanced

8597:    Notes:
8598:    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.

8600:    See `MatSetNullSpace()`

8602: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8603: @*/
8604: PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8605: {
8608:   if (nullsp) PetscObjectReference((PetscObject)nullsp);
8609:   MatNullSpaceDestroy(&mat->transnullsp);
8610:   mat->transnullsp = nullsp;
8611:   return 0;
8612: }

8614: /*@
8615:    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8616:         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.

8618:    Logically Collective on mat

8620:    Input Parameters:
8621: +  mat - the matrix
8622: -  nullsp - the null space object

8624:    Level: advanced

8626:    Notes:
8627:    Overwrites any previous near null space that may have been attached

8629:    You can remove the null space by calling this routine with an nullsp of NULL

8631: .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8632: @*/
8633: PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8634: {
8638:   MatCheckPreallocated(mat, 1);
8639:   if (nullsp) PetscObjectReference((PetscObject)nullsp);
8640:   MatNullSpaceDestroy(&mat->nearnullsp);
8641:   mat->nearnullsp = nullsp;
8642:   return 0;
8643: }

8645: /*@
8646:    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`

8648:    Not Collective

8650:    Input Parameter:
8651: .  mat - the matrix

8653:    Output Parameter:
8654: .  nullsp - the null space object, NULL if not set

8656:    Level: advanced

8658: .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8659: @*/
8660: PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8661: {
8665:   MatCheckPreallocated(mat, 1);
8666:   *nullsp = mat->nearnullsp;
8667:   return 0;
8668: }

8670: /*@C
8671:    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.

8673:    Collective on mat

8675:    Input Parameters:
8676: +  mat - the matrix
8677: .  row - row/column permutation
8678: .  fill - expected fill factor >= 1.0
8679: -  level - level of fill, for ICC(k)

8681:    Notes:
8682:    Probably really in-place only when level of fill is zero, otherwise allocates
8683:    new space to store factored matrix and deletes previous memory.

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

8689:    Level: developer

8691:    Developer Note:
8692:    The Fortran interface is not autogenerated as the f90
8693:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

8695: .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8696: @*/
8697: PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8698: {
8706:   MatCheckPreallocated(mat, 1);
8707:   PetscUseTypeMethod(mat, iccfactor, row, info);
8708:   PetscObjectStateIncrease((PetscObject)mat);
8709:   return 0;
8710: }

8712: /*@
8713:    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8714:          ghosted ones.

8716:    Not Collective

8718:    Input Parameters:
8719: +  mat - the matrix
8720: -  diag - the diagonal values, including ghost ones

8722:    Level: developer

8724:    Notes:
8725:     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices

8727:     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`

8729: .seealso: `MatDiagonalScale()`
8730: @*/
8731: PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8732: {
8733:   PetscMPIInt size;


8740:   PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0);
8741:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
8742:   if (size == 1) {
8743:     PetscInt n, m;
8744:     VecGetSize(diag, &n);
8745:     MatGetSize(mat, NULL, &m);
8746:     if (m == n) {
8747:       MatDiagonalScale(mat, NULL, diag);
8748:     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8749:   } else {
8750:     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8751:   }
8752:   PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0);
8753:   PetscObjectStateIncrease((PetscObject)mat);
8754:   return 0;
8755: }

8757: /*@
8758:    MatGetInertia - Gets the inertia from a factored matrix

8760:    Collective on mat

8762:    Input Parameter:
8763: .  mat - the matrix

8765:    Output Parameters:
8766: +   nneg - number of negative eigenvalues
8767: .   nzero - number of zero eigenvalues
8768: -   npos - number of positive eigenvalues

8770:    Level: advanced

8772:    Note:
8773:     Matrix must have been factored by `MatCholeskyFactor()`

8775: .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8776: @*/
8777: PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8778: {
8783:   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8784:   return 0;
8785: }

8787: /* ----------------------------------------------------------------*/
8788: /*@C
8789:    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors

8791:    Neighbor-wise Collective on mat

8793:    Input Parameters:
8794: +  mat - the factored matrix obtained with `MatGetFactor()`
8795: -  b - the right-hand-side vectors

8797:    Output Parameter:
8798: .  x - the result vectors

8800:    Note:
8801:    The vectors b and x cannot be the same.  I.e., one cannot
8802:    call `MatSolves`(A,x,x).

8804:    Level: developer

8806: .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8807: @*/
8808: PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
8809: {
8814:   if (!mat->rmap->N && !mat->cmap->N) return 0;

8816:   MatCheckPreallocated(mat, 1);
8817:   PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0);
8818:   PetscUseTypeMethod(mat, solves, b, x);
8819:   PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0);
8820:   return 0;
8821: }

8823: /*@
8824:    MatIsSymmetric - Test whether a matrix is symmetric

8826:    Collective on mat

8828:    Input Parameters:
8829: +  A - the matrix to test
8830: -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)

8832:    Output Parameters:
8833: .  flg - the result

8835:    Notes:
8836:     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results

8838:     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`

8840:     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8841:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

8843:    Level: intermediate

8845: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
8846:           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8847: @*/
8848: PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
8849: {

8853:   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8854:   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8855:   else {
8856:     if (!A->ops->issymmetric) {
8857:       MatType mattype;
8858:       MatGetType(A, &mattype);
8859:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8860:     }
8861:     PetscUseTypeMethod(A, issymmetric, tol, flg);
8862:     if (!tol) MatSetOption(A, MAT_SYMMETRIC, *flg);
8863:   }
8864:   return 0;
8865: }

8867: /*@
8868:    MatIsHermitian - Test whether a matrix is Hermitian

8870:    Collective on Mat

8872:    Input Parameters:
8873: +  A - the matrix to test
8874: -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)

8876:    Output Parameters:
8877: .  flg - the result

8879:    Level: intermediate

8881:    Notes:
8882:     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results

8884:     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`

8886:     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8887:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)

8889: .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8890:           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8891: @*/
8892: PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
8893: {

8897:   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8898:   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8899:   else {
8900:     if (!A->ops->ishermitian) {
8901:       MatType mattype;
8902:       MatGetType(A, &mattype);
8903:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8904:     }
8905:     PetscUseTypeMethod(A, ishermitian, tol, flg);
8906:     if (!tol) MatSetOption(A, MAT_HERMITIAN, *flg);
8907:   }
8908:   return 0;
8909: }

8911: /*@
8912:    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state

8914:    Not Collective

8916:    Input Parameter:
8917: .  A - the matrix to check

8919:    Output Parameters:
8920: +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
8921: -  flg - the result (only valid if set is `PETSC_TRUE`)

8923:    Level: advanced

8925:    Notes:
8926:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
8927:    if you want it explicitly checked

8929:     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8930:     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

8932: .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8933: @*/
8934: PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
8935: {
8939:   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8940:     *set = PETSC_TRUE;
8941:     *flg = PetscBool3ToBool(A->symmetric);
8942:   } else {
8943:     *set = PETSC_FALSE;
8944:   }
8945:   return 0;
8946: }

8948: /*@
8949:    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state

8951:    Not Collective

8953:    Input Parameter:
8954: .  A - the matrix to check

8956:    Output Parameters:
8957: +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
8958: -  flg - the result (only valid if set is `PETSC_TRUE`)

8960:    Level: advanced

8962:    Notes:
8963:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).

8965:    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
8966:    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)

8968: .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8969: @*/
8970: PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
8971: {
8975:   if (A->spd != PETSC_BOOL3_UNKNOWN) {
8976:     *set = PETSC_TRUE;
8977:     *flg = PetscBool3ToBool(A->spd);
8978:   } else {
8979:     *set = PETSC_FALSE;
8980:   }
8981:   return 0;
8982: }

8984: /*@
8985:    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state

8987:    Not Collective

8989:    Input Parameter:
8990: .  A - the matrix to check

8992:    Output Parameters:
8993: +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
8994: -  flg - the result (only valid if set is `PETSC_TRUE`)

8996:    Level: advanced

8998:    Notes:
8999:    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9000:    if you want it explicitly checked

9002:    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9003:    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9005: .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9006: @*/
9007: PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9008: {
9012:   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9013:     *set = PETSC_TRUE;
9014:     *flg = PetscBool3ToBool(A->hermitian);
9015:   } else {
9016:     *set = PETSC_FALSE;
9017:   }
9018:   return 0;
9019: }

9021: /*@
9022:    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric

9024:    Collective on Mat

9026:    Input Parameter:
9027: .  A - the matrix to test

9029:    Output Parameters:
9030: .  flg - the result

9032:    Notes:
9033:    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`

9035:    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
9036:    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9038:    Level: intermediate

9040: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9041: @*/
9042: PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9043: {
9046:   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9047:     *flg = PetscBool3ToBool(A->structurally_symmetric);
9048:   } else {
9049:     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9050:     MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg);
9051:   }
9052:   return 0;
9053: }

9055: /*@
9056:    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state

9058:    Not Collective

9060:    Input Parameter:
9061: .  A - the matrix to check

9063:    Output Parameters:
9064: +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9065: -  flg - the result (only valid if set is PETSC_TRUE)

9067:    Level: advanced

9069:    Notes:
9070:    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
9071:    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)

9073:    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)

9075: .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9076: @*/
9077: PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9078: {
9082:   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9083:     *set = PETSC_TRUE;
9084:     *flg = PetscBool3ToBool(A->structurally_symmetric);
9085:   } else {
9086:     *set = PETSC_FALSE;
9087:   }
9088:   return 0;
9089: }

9091: /*@
9092:    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9093:        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process

9095:     Not collective

9097:    Input Parameter:
9098: .   mat - the matrix

9100:    Output Parameters:
9101: +   nstash   - the size of the stash
9102: .   reallocs - the number of additional mallocs incurred.
9103: .   bnstash   - the size of the block stash
9104: -   breallocs - the number of additional mallocs incurred.in the block stash

9106:    Level: advanced

9108: .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9109: @*/
9110: PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9111: {
9112:   MatStashGetInfo_Private(&mat->stash, nstash, reallocs);
9113:   MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs);
9114:   return 0;
9115: }

9117: /*@C
9118:    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9119:    parallel layout, `PetscLayout` for rows and columns

9121:    Collective on mat

9123:    Input Parameter:
9124: .  mat - the matrix

9126:    Output Parameters:
9127: +   right - (optional) vector that the matrix can be multiplied against
9128: -   left - (optional) vector that the matrix vector product can be stored in

9130:    Notes:
9131:     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()`.

9133:     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed

9135:   Level: advanced

9137: .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9138: @*/
9139: PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9140: {
9143:   if (mat->ops->getvecs) {
9144:     PetscUseTypeMethod(mat, getvecs, right, left);
9145:   } else {
9146:     PetscInt rbs, cbs;
9147:     MatGetBlockSizes(mat, &rbs, &cbs);
9148:     if (right) {
9150:       VecCreate(PetscObjectComm((PetscObject)mat), right);
9151:       VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE);
9152:       VecSetBlockSize(*right, cbs);
9153:       VecSetType(*right, mat->defaultvectype);
9154: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9155:       if (mat->boundtocpu && mat->bindingpropagates) {
9156:         VecSetBindingPropagates(*right, PETSC_TRUE);
9157:         VecBindToCPU(*right, PETSC_TRUE);
9158:       }
9159: #endif
9160:       PetscLayoutReference(mat->cmap, &(*right)->map);
9161:     }
9162:     if (left) {
9164:       VecCreate(PetscObjectComm((PetscObject)mat), left);
9165:       VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE);
9166:       VecSetBlockSize(*left, rbs);
9167:       VecSetType(*left, mat->defaultvectype);
9168: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9169:       if (mat->boundtocpu && mat->bindingpropagates) {
9170:         VecSetBindingPropagates(*left, PETSC_TRUE);
9171:         VecBindToCPU(*left, PETSC_TRUE);
9172:       }
9173: #endif
9174:       PetscLayoutReference(mat->rmap, &(*left)->map);
9175:     }
9176:   }
9177:   return 0;
9178: }

9180: /*@C
9181:    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9182:      with default values.

9184:    Not Collective

9186:    Input Parameters:
9187: .    info - the `MatFactorInfo` data structure

9189:    Notes:
9190:     The solvers are generally used through the `KSP` and `PC` objects, for example
9191:           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`

9193:     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed

9195:    Level: developer

9197:    Developer Note:
9198:    The Fortran interface is not autogenerated as the f90
9199:    interface definition cannot be generated correctly [due to `MatFactorInfo`]

9201: .seealso: `MatGetFactor()`, `MatFactorInfo`
9202: @*/
9203: PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9204: {
9205:   PetscMemzero(info, sizeof(MatFactorInfo));
9206:   return 0;
9207: }

9209: /*@
9210:    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed

9212:    Collective on mat

9214:    Input Parameters:
9215: +  mat - the factored matrix
9216: -  is - the index set defining the Schur indices (0-based)

9218:    Notes:
9219:     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.

9221:    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.

9223:    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`

9225:    Level: advanced

9227: .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9228:           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`

9230: @*/
9231: PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9232: {
9233:   PetscErrorCode (*f)(Mat, IS);

9241:   PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f);
9243:   MatDestroy(&mat->schur);
9244:   (*f)(mat, is);
9246:   return 0;
9247: }

9249: /*@
9250:   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step

9252:    Logically Collective on mat

9254:    Input Parameters:
9255: +  F - the factored matrix obtained by calling `MatGetFactor()`
9256: .  S - location where to return the Schur complement, can be NULL
9257: -  status - the status of the Schur complement matrix, can be NULL

9259:    Notes:
9260:    You must call `MatFactorSetSchurIS()` before calling this routine.

9262:    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`

9264:    The routine provides a copy of the Schur matrix stored within the solver data structures.
9265:    The caller must destroy the object when it is no longer needed.
9266:    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.

9268:    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)

9270:    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.

9272:    Developer Note:
9273:     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9274:    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.

9276:    Level: advanced

9278: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9279: @*/
9280: PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9281: {
9285:   if (S) {
9286:     PetscErrorCode (*f)(Mat, Mat *);

9288:     PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f);
9289:     if (f) {
9290:       (*f)(F, S);
9291:     } else {
9292:       MatDuplicate(F->schur, MAT_COPY_VALUES, S);
9293:     }
9294:   }
9295:   if (status) *status = F->schur_status;
9296:   return 0;
9297: }

9299: /*@
9300:   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix

9302:    Logically Collective on mat

9304:    Input Parameters:
9305: +  F - the factored matrix obtained by calling `MatGetFactor()`
9306: .  *S - location where to return the Schur complement, can be NULL
9307: -  status - the status of the Schur complement matrix, can be NULL

9309:    Notes:
9310:    You must call `MatFactorSetSchurIS()` before calling this routine.

9312:    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`

9314:    The routine returns a the Schur Complement stored within the data strutures of the solver.

9316:    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.

9318:    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.

9320:    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix

9322:    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.

9324:    Level: advanced

9326: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9327: @*/
9328: PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9329: {
9333:   if (S) *S = F->schur;
9334:   if (status) *status = F->schur_status;
9335:   return 0;
9336: }

9338: /*@
9339:   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`

9341:    Logically Collective on mat

9343:    Input Parameters:
9344: +  F - the factored matrix obtained by calling `MatGetFactor()`
9345: .  *S - location where the Schur complement is stored
9346: -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)

9348:    Level: advanced

9350: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9351: @*/
9352: PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9353: {
9355:   if (S) {
9357:     *S = NULL;
9358:   }
9359:   F->schur_status = status;
9360:   MatFactorUpdateSchurStatus_Private(F);
9361:   return 0;
9362: }

9364: /*@
9365:   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step

9367:    Logically Collective on mat

9369:    Input Parameters:
9370: +  F - the factored matrix obtained by calling `MatGetFactor()`
9371: .  rhs - location where the right hand side of the Schur complement system is stored
9372: -  sol - location where the solution of the Schur complement system has to be returned

9374:    Notes:
9375:    The sizes of the vectors should match the size of the Schur complement

9377:    Must be called after `MatFactorSetSchurIS()`

9379:    Level: advanced

9381: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9382: @*/
9383: PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9384: {
9393:   MatFactorFactorizeSchurComplement(F);
9394:   switch (F->schur_status) {
9395:   case MAT_FACTOR_SCHUR_FACTORED:
9396:     MatSolveTranspose(F->schur, rhs, sol);
9397:     break;
9398:   case MAT_FACTOR_SCHUR_INVERTED:
9399:     MatMultTranspose(F->schur, rhs, sol);
9400:     break;
9401:   default:
9402:     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9403:   }
9404:   return 0;
9405: }

9407: /*@
9408:   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step

9410:    Logically Collective on mat

9412:    Input Parameters:
9413: +  F - the factored matrix obtained by calling `MatGetFactor()`
9414: .  rhs - location where the right hand side of the Schur complement system is stored
9415: -  sol - location where the solution of the Schur complement system has to be returned

9417:    Notes:
9418:    The sizes of the vectors should match the size of the Schur complement

9420:    Must be called after `MatFactorSetSchurIS()`

9422:    Level: advanced

9424: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9425: @*/
9426: PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9427: {
9436:   MatFactorFactorizeSchurComplement(F);
9437:   switch (F->schur_status) {
9438:   case MAT_FACTOR_SCHUR_FACTORED:
9439:     MatSolve(F->schur, rhs, sol);
9440:     break;
9441:   case MAT_FACTOR_SCHUR_INVERTED:
9442:     MatMult(F->schur, rhs, sol);
9443:     break;
9444:   default:
9445:     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9446:   }
9447:   return 0;
9448: }

9450: /*@
9451:   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step

9453:    Logically Collective on F

9455:    Input Parameters:
9456: .  F - the factored matrix obtained by calling `MatGetFactor()`

9458:    Notes:
9459:     Must be called after `MatFactorSetSchurIS()`.

9461:    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.

9463:    Level: advanced

9465: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9466: @*/
9467: PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9468: {
9471:   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) return 0;
9472:   MatFactorFactorizeSchurComplement(F);
9473:   MatFactorInvertSchurComplement_Private(F);
9474:   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9475:   return 0;
9476: }

9478: /*@
9479:   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step

9481:    Logically Collective on mat

9483:    Input Parameters:
9484: .  F - the factored matrix obtained by calling `MatGetFactor()`

9486:    Note:
9487:     Must be called after `MatFactorSetSchurIS()`

9489:    Level: advanced

9491: .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9492: @*/
9493: PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9494: {
9497:   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) return 0;
9498:   MatFactorFactorizeSchurComplement_Private(F);
9499:   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9500:   return 0;
9501: }

9503: /*@
9504:    MatPtAP - Creates the matrix product C = P^T * A * P

9506:    Neighbor-wise Collective on A

9508:    Input Parameters:
9509: +  A - the matrix
9510: .  P - the projection matrix
9511: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9512: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9513:           if the result is a dense matrix this is irrelevant

9515:    Output Parameters:
9516: .  C - the product matrix

9518:    Notes:
9519:    C will be created and must be destroyed by the user with `MatDestroy()`.

9521:    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done

9523:    Developer Note:
9524:    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.

9526:    Level: intermediate

9528: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9529: @*/
9530: PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9531: {
9532:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);

9535:   if (scall == MAT_INITIAL_MATRIX) {
9536:     MatProductCreate(A, P, NULL, C);
9537:     MatProductSetType(*C, MATPRODUCT_PtAP);
9538:     MatProductSetAlgorithm(*C, "default");
9539:     MatProductSetFill(*C, fill);

9541:     (*C)->product->api_user = PETSC_TRUE;
9542:     MatProductSetFromOptions(*C);
9544:     MatProductSymbolic(*C);
9545:   } else { /* scall == MAT_REUSE_MATRIX */
9546:     MatProductReplaceMats(A, P, NULL, *C);
9547:   }

9549:   MatProductNumeric(*C);
9550:   (*C)->symmetric = A->symmetric;
9551:   (*C)->spd       = A->spd;
9552:   return 0;
9553: }

9555: /*@
9556:    MatRARt - Creates the matrix product C = R * A * R^T

9558:    Neighbor-wise Collective on A

9560:    Input Parameters:
9561: +  A - the matrix
9562: .  R - the projection matrix
9563: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9564: -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9565:           if the result is a dense matrix this is irrelevant

9567:    Output Parameters:
9568: .  C - the product matrix

9570:    Notes:
9571:    C will be created and must be destroyed by the user with `MatDestroy()`.

9573:    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done

9575:    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9576:    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9577:    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9578:    We recommend using MatPtAP().

9580:    Level: intermediate

9582: .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9583: @*/
9584: PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9585: {
9586:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);

9589:   if (scall == MAT_INITIAL_MATRIX) {
9590:     MatProductCreate(A, R, NULL, C);
9591:     MatProductSetType(*C, MATPRODUCT_RARt);
9592:     MatProductSetAlgorithm(*C, "default");
9593:     MatProductSetFill(*C, fill);

9595:     (*C)->product->api_user = PETSC_TRUE;
9596:     MatProductSetFromOptions(*C);
9598:     MatProductSymbolic(*C);
9599:   } else { /* scall == MAT_REUSE_MATRIX */
9600:     MatProductReplaceMats(A, R, NULL, *C);
9601:   }

9603:   MatProductNumeric(*C);
9604:   if (A->symmetric == PETSC_BOOL3_TRUE) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9605:   return 0;
9606: }

9608: static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9609: {

9612:   if (scall == MAT_INITIAL_MATRIX) {
9613:     PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]);
9614:     MatProductCreate(A, B, NULL, C);
9615:     MatProductSetType(*C, ptype);
9616:     MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT);
9617:     MatProductSetFill(*C, fill);

9619:     (*C)->product->api_user = PETSC_TRUE;
9620:     MatProductSetFromOptions(*C);
9621:     MatProductSymbolic(*C);
9622:   } else { /* scall == MAT_REUSE_MATRIX */
9623:     Mat_Product *product = (*C)->product;
9624:     PetscBool    isdense;

9626:     PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "");
9627:     if (isdense && product && product->type != ptype) {
9628:       MatProductClear(*C);
9629:       product = NULL;
9630:     }
9631:     PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]);
9632:     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9633:       if (isdense) {
9634:         MatProductCreate_Private(A, B, NULL, *C);
9635:         product           = (*C)->product;
9636:         product->fill     = fill;
9637:         product->api_user = PETSC_TRUE;
9638:         product->clear    = PETSC_TRUE;

9640:         MatProductSetType(*C, ptype);
9641:         MatProductSetFromOptions(*C);
9643:         MatProductSymbolic(*C);
9644:       } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9645:     } else { /* user may change input matrices A or B when REUSE */
9646:       MatProductReplaceMats(A, B, NULL, *C);
9647:     }
9648:   }
9649:   MatProductNumeric(*C);
9650:   return 0;
9651: }

9653: /*@
9654:    MatMatMult - Performs matrix-matrix multiplication C=A*B.

9656:    Neighbor-wise Collective on A

9658:    Input Parameters:
9659: +  A - the left matrix
9660: .  B - the right matrix
9661: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9662: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9663:           if the result is a dense matrix this is irrelevant

9665:    Output Parameters:
9666: .  C - the product matrix

9668:    Notes:
9669:    Unless scall is `MAT_REUSE_MATRIX` C will be created.

9671:    `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
9672:    call to this function with `MAT_INITIAL_MATRIX`.

9674:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.

9676:    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`,
9677:    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.

9679:    Example of Usage:
9680: .vb
9681:      MatProductCreate(A,B,NULL,&C);
9682:      MatProductSetType(C,MATPRODUCT_AB);
9683:      MatProductSymbolic(C);
9684:      MatProductNumeric(C); // compute C=A * B
9685:      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9686:      MatProductNumeric(C);
9687:      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9688:      MatProductNumeric(C);
9689: .ve

9691:    Level: intermediate

9693: .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9694: @*/
9695: PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9696: {
9697:   MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C);
9698:   return 0;
9699: }

9701: /*@
9702:    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.

9704:    Neighbor-wise Collective on A

9706:    Input Parameters:
9707: +  A - the left matrix
9708: .  B - the right matrix
9709: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9710: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known

9712:    Output Parameters:
9713: .  C - the product matrix

9715:    Notes:
9716:    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.

9718:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call

9720:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9721:    actually needed.

9723:    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9724:    and for pairs of `MATMPIDENSE` matrices.

9726:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`

9728:    Options Database Keys:
9729: .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9730:               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9731:               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.

9733:    Level: intermediate

9735: .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9736: @*/
9737: PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9738: {
9739:   MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C);
9740:   if (A == B) MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE);
9741:   return 0;
9742: }

9744: /*@
9745:    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.

9747:    Neighbor-wise Collective on A

9749:    Input Parameters:
9750: +  A - the left matrix
9751: .  B - the right matrix
9752: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9753: -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known

9755:    Output Parameters:
9756: .  C - the product matrix

9758:    Notes:
9759:    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.

9761:    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.

9763:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`

9765:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9766:    actually needed.

9768:    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9769:    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.

9771:    Level: intermediate

9773: .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9774: @*/
9775: PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9776: {
9777:   MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C);
9778:   return 0;
9779: }

9781: /*@
9782:    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.

9784:    Neighbor-wise Collective on A

9786:    Input Parameters:
9787: +  A - the left matrix
9788: .  B - the middle matrix
9789: .  C - the right matrix
9790: .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9791: -  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
9792:           if the result is a dense matrix this is irrelevant

9794:    Output Parameters:
9795: .  D - the product matrix

9797:    Notes:
9798:    Unless scall is `MAT_REUSE_MATRIX` D will be created.

9800:    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call

9802:    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`

9804:    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9805:    actually needed.

9807:    If you have many matrices with the same non-zero structure to multiply, you
9808:    should use `MAT_REUSE_MATRIX` in all calls but the first

9810:    Level: intermediate

9812: .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9813: @*/
9814: PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
9815: {
9816:   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);

9819:   if (scall == MAT_INITIAL_MATRIX) {
9820:     MatProductCreate(A, B, C, D);
9821:     MatProductSetType(*D, MATPRODUCT_ABC);
9822:     MatProductSetAlgorithm(*D, "default");
9823:     MatProductSetFill(*D, fill);

9825:     (*D)->product->api_user = PETSC_TRUE;
9826:     MatProductSetFromOptions(*D);
9828:                ((PetscObject)C)->type_name);
9829:     MatProductSymbolic(*D);
9830:   } else { /* user may change input matrices when REUSE */
9831:     MatProductReplaceMats(A, B, C, *D);
9832:   }
9833:   MatProductNumeric(*D);
9834:   return 0;
9835: }

9837: /*@
9838:    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.

9840:    Collective on mat

9842:    Input Parameters:
9843: +  mat - the matrix
9844: .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9845: .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
9846: -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

9848:    Output Parameter:
9849: .  matredundant - redundant matrix

9851:    Notes:
9852:    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
9853:    original matrix has not changed from that last call to MatCreateRedundantMatrix().

9855:    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9856:    calling it.

9858:    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.

9860:    Level: advanced

9862: .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
9863: @*/
9864: PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
9865: {
9866:   MPI_Comm       comm;
9867:   PetscMPIInt    size;
9868:   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9869:   Mat_Redundant *redund     = NULL;
9870:   PetscSubcomm   psubcomm   = NULL;
9871:   MPI_Comm       subcomm_in = subcomm;
9872:   Mat           *matseq;
9873:   IS             isrow, iscol;
9874:   PetscBool      newsubcomm = PETSC_FALSE;

9877:   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9880:   }

9882:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
9883:   if (size == 1 || nsubcomm == 1) {
9884:     if (reuse == MAT_INITIAL_MATRIX) {
9885:       MatDuplicate(mat, MAT_COPY_VALUES, matredundant);
9886:     } else {
9888:       MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN);
9889:     }
9890:     return 0;
9891:   }

9895:   MatCheckPreallocated(mat, 1);

9897:   PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0);
9898:   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9899:     /* create psubcomm, then get subcomm */
9900:     PetscObjectGetComm((PetscObject)mat, &comm);
9901:     MPI_Comm_size(comm, &size);

9904:     PetscSubcommCreate(comm, &psubcomm);
9905:     PetscSubcommSetNumber(psubcomm, nsubcomm);
9906:     PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS);
9907:     PetscSubcommSetFromOptions(psubcomm);
9908:     PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL);
9909:     newsubcomm = PETSC_TRUE;
9910:     PetscSubcommDestroy(&psubcomm);
9911:   }

9913:   /* get isrow, iscol and a local sequential matrix matseq[0] */
9914:   if (reuse == MAT_INITIAL_MATRIX) {
9915:     mloc_sub = PETSC_DECIDE;
9916:     nloc_sub = PETSC_DECIDE;
9917:     if (bs < 1) {
9918:       PetscSplitOwnership(subcomm, &mloc_sub, &M);
9919:       PetscSplitOwnership(subcomm, &nloc_sub, &N);
9920:     } else {
9921:       PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M);
9922:       PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N);
9923:     }
9924:     MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm);
9925:     rstart = rend - mloc_sub;
9926:     ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow);
9927:     ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol);
9928:   } else { /* reuse == MAT_REUSE_MATRIX */
9930:     /* retrieve subcomm */
9931:     PetscObjectGetComm((PetscObject)(*matredundant), &subcomm);
9932:     redund = (*matredundant)->redundant;
9933:     isrow  = redund->isrow;
9934:     iscol  = redund->iscol;
9935:     matseq = redund->matseq;
9936:   }
9937:   MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq);

9939:   /* get matredundant over subcomm */
9940:   if (reuse == MAT_INITIAL_MATRIX) {
9941:     MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant);

9943:     /* create a supporting struct and attach it to C for reuse */
9944:     PetscNew(&redund);
9945:     (*matredundant)->redundant = redund;
9946:     redund->isrow              = isrow;
9947:     redund->iscol              = iscol;
9948:     redund->matseq             = matseq;
9949:     if (newsubcomm) {
9950:       redund->subcomm = subcomm;
9951:     } else {
9952:       redund->subcomm = MPI_COMM_NULL;
9953:     }
9954:   } else {
9955:     MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant);
9956:   }
9957: #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9958:   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
9959:     MatBindToCPU(*matredundant, PETSC_TRUE);
9960:     MatSetBindingPropagates(*matredundant, PETSC_TRUE);
9961:   }
9962: #endif
9963:   PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0);
9964:   return 0;
9965: }

9967: /*@C
9968:    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
9969:    a given `Mat`. Each submatrix can span multiple procs.

9971:    Collective on mat

9973:    Input Parameters:
9974: +  mat - the matrix
9975: .  subcomm - the subcommunicator obtained by MPI_Com_split(comm)
9976: -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

9978:    Output Parameter:
9979: .  subMat - 'parallel submatrices each spans a given subcomm

9981:   Notes:
9982:   The submatrix partition across processors is dictated by 'subComm' a
9983:   communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
9984:   is not restriced to be grouped with consecutive original ranks.

9986:   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
9987:   map directly to the layout of the original matrix [wrt the local
9988:   row,col partitioning]. So the original 'DiagonalMat' naturally maps
9989:   into the 'DiagonalMat' of the subMat, hence it is used directly from
9990:   the subMat. However the offDiagMat looses some columns - and this is
9991:   reconstructed with `MatSetValues()`

9993:   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks

9995:   Level: advanced

9997: .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
9998: @*/
9999: PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10000: {
10001:   PetscMPIInt commsize, subCommSize;

10003:   MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize);
10004:   MPI_Comm_size(subComm, &subCommSize);

10008:   PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10009:   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10010:   PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0);
10011:   return 0;
10012: }

10014: /*@
10015:    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering

10017:    Not Collective

10019:    Input Parameters:
10020: +  mat - matrix to extract local submatrix from
10021: .  isrow - local row indices for submatrix
10022: -  iscol - local column indices for submatrix

10024:    Output Parameter:
10025: .  submat - the submatrix

10027:    Level: intermediate

10029:    Notes:
10030:    The submat should be returned with `MatRestoreLocalSubMatrix()`.

10032:    Depending on the format of mat, the returned submat may not implement `MatMult()`.  Its communicator may be
10033:    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.

10035:    The submat always implements `MatSetValuesLocal()`.  If isrow and iscol have the same block size, then
10036:    `MatSetValuesBlockedLocal()` will also be implemented.

10038:    The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10039:    Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.

10041: .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10042: @*/
10043: PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10044: {

10052:   if (mat->ops->getlocalsubmatrix) {
10053:     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10054:   } else {
10055:     MatCreateLocalRef(mat, isrow, iscol, submat);
10056:   }
10057:   return 0;
10058: }

10060: /*@
10061:    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`

10063:    Not Collective

10065:    Input Parameters:
10066: +  mat - matrix to extract local submatrix from
10067: .  isrow - local row indices for submatrix
10068: .  iscol - local column indices for submatrix
10069: -  submat - the submatrix

10071:    Level: intermediate

10073: .seealso: `MatGetLocalSubMatrix()`
10074: @*/
10075: PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10076: {

10084:   if (mat->ops->restorelocalsubmatrix) {
10085:     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10086:   } else {
10087:     MatDestroy(submat);
10088:   }
10089:   *submat = NULL;
10090:   return 0;
10091: }

10093: /* --------------------------------------------------------*/
10094: /*@
10095:    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix

10097:    Collective on mat

10099:    Input Parameter:
10100: .  mat - the matrix

10102:    Output Parameter:
10103: .  is - if any rows have zero diagonals this contains the list of them

10105:    Level: developer

10107: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10108: @*/
10109: PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10110: {

10116:   if (!mat->ops->findzerodiagonals) {
10117:     Vec                diag;
10118:     const PetscScalar *a;
10119:     PetscInt          *rows;
10120:     PetscInt           rStart, rEnd, r, nrow = 0;

10122:     MatCreateVecs(mat, &diag, NULL);
10123:     MatGetDiagonal(mat, diag);
10124:     MatGetOwnershipRange(mat, &rStart, &rEnd);
10125:     VecGetArrayRead(diag, &a);
10126:     for (r = 0; r < rEnd - rStart; ++r)
10127:       if (a[r] == 0.0) ++nrow;
10128:     PetscMalloc1(nrow, &rows);
10129:     nrow = 0;
10130:     for (r = 0; r < rEnd - rStart; ++r)
10131:       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10132:     VecRestoreArrayRead(diag, &a);
10133:     VecDestroy(&diag);
10134:     ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is);
10135:   } else {
10136:     PetscUseTypeMethod(mat, findzerodiagonals, is);
10137:   }
10138:   return 0;
10139: }

10141: /*@
10142:    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)

10144:    Collective on mat

10146:    Input Parameter:
10147: .  mat - the matrix

10149:    Output Parameter:
10150: .  is - contains the list of rows with off block diagonal entries

10152:    Level: developer

10154: .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10155: @*/
10156: PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10157: {

10163:   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10164:   return 0;
10165: }

10167: /*@C
10168:   MatInvertBlockDiagonal - Inverts the block diagonal entries.

10170:   Collective on mat

10172:   Input Parameters:
10173: . mat - the matrix

10175:   Output Parameters:
10176: . values - the block inverses in column major order (FORTRAN-like)

10178:    Notes:
10179:    The size of the blocks is determined by the block size of the matrix.

10181:    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case

10183:    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size

10185:    Fortran Note:
10186:      This routine is not available from Fortran.

10188:   Level: advanced

10190: .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10191: @*/
10192: PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10193: {
10197:   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10198:   return 0;
10199: }

10201: /*@C
10202:   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.

10204:   Collective on mat

10206:   Input Parameters:
10207: + mat - the matrix
10208: . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10209: - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`

10211:   Output Parameters:
10212: . values - the block inverses in column major order (FORTRAN-like)

10214:   Notes:
10215:   Use `MatInvertBlockDiagonal()` if all blocks have the same size

10217:   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case

10219:   Fortran Note:
10220:   This routine is not available from Fortran.

10222:   Level: advanced

10224: .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10225: @*/
10226: PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10227: {
10231:   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10232:   return 0;
10233: }

10235: /*@
10236:   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A

10238:   Collective on Mat

10240:   Input Parameters:
10241: + A - the matrix
10242: - C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.

10244:   Note:
10245:   The blocksize of the matrix is used to determine the blocks on the diagonal of C

10247:   Level: advanced

10249: .seealso: `MatInvertBlockDiagonal()`
10250: @*/
10251: PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10252: {
10253:   const PetscScalar *vals;
10254:   PetscInt          *dnnz;
10255:   PetscInt           m, rstart, rend, bs, i, j;

10257:   MatInvertBlockDiagonal(A, &vals);
10258:   MatGetBlockSize(A, &bs);
10259:   MatGetLocalSize(A, &m, NULL);
10260:   MatSetLayouts(C, A->rmap, A->cmap);
10261:   PetscMalloc1(m / bs, &dnnz);
10262:   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10263:   MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL);
10264:   PetscFree(dnnz);
10265:   MatGetOwnershipRange(C, &rstart, &rend);
10266:   MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE);
10267:   for (i = rstart / bs; i < rend / bs; i++) MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES);
10268:   MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY);
10269:   MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY);
10270:   MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE);
10271:   return 0;
10272: }

10274: /*@C
10275:     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10276:     via `MatTransposeColoringCreate()`.

10278:     Collective on c

10280:     Input Parameter:
10281: .   c - coloring context

10283:     Level: intermediate

10285: .seealso: `MatTransposeColoringCreate()`
10286: @*/
10287: PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10288: {
10289:   MatTransposeColoring matcolor = *c;

10291:   if (!matcolor) return 0;
10292:   if (--((PetscObject)matcolor)->refct > 0) {
10293:     matcolor = NULL;
10294:     return 0;
10295:   }

10297:   PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow);
10298:   PetscFree(matcolor->rows);
10299:   PetscFree(matcolor->den2sp);
10300:   PetscFree(matcolor->colorforcol);
10301:   PetscFree(matcolor->columns);
10302:   if (matcolor->brows > 0) PetscFree(matcolor->lstart);
10303:   PetscHeaderDestroy(c);
10304:   return 0;
10305: }

10307: /*@C
10308:     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10309:     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10310:     `MatTransposeColoring` to sparse B.

10312:     Collective on coloring

10314:     Input Parameters:
10315: +   B - sparse matrix B
10316: .   Btdense - symbolic dense matrix B^T
10317: -   coloring - coloring context created with `MatTransposeColoringCreate()`

10319:     Output Parameter:
10320: .   Btdense - dense matrix B^T

10322:     Level: developer

10324:     Note:
10325:     These are used internally for some implementations of `MatRARt()`

10327: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`

10329: @*/
10330: PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10331: {

10336:   (B->ops->transcoloringapplysptoden)(coloring, B, Btdense);
10337:   return 0;
10338: }

10340: /*@C
10341:     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10342:     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10343:     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10344:     Csp from Cden.

10346:     Collective on matcoloring

10348:     Input Parameters:
10349: +   coloring - coloring context created with `MatTransposeColoringCreate()`
10350: -   Cden - matrix product of a sparse matrix and a dense matrix Btdense

10352:     Output Parameter:
10353: .   Csp - sparse matrix

10355:     Level: developer

10357:     Note:
10358:     These are used internally for some implementations of `MatRARt()`

10360: .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`

10362: @*/
10363: PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10364: {

10369:   (Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp);
10370:   MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY);
10371:   MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY);
10372:   return 0;
10373: }

10375: /*@C
10376:    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.

10378:    Collective on mat

10380:    Input Parameters:
10381: +  mat - the matrix product C
10382: -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`

10384:     Output Parameter:
10385: .   color - the new coloring context

10387:     Level: intermediate

10389: .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10390:           `MatTransColoringApplyDenToSp()`
10391: @*/
10392: PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10393: {
10394:   MatTransposeColoring c;
10395:   MPI_Comm             comm;

10397:   PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10398:   PetscObjectGetComm((PetscObject)mat, &comm);
10399:   PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL);

10401:   c->ctype = iscoloring->ctype;
10402:   if (mat->ops->transposecoloringcreate) {
10403:     PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10404:   } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);

10406:   *color = c;
10407:   PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0);
10408:   return 0;
10409: }

10411: /*@
10412:       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10413:         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10414:         same, otherwise it will be larger

10416:      Not Collective

10418:   Input Parameter:
10419: .    A  - the matrix

10421:   Output Parameter:
10422: .    state - the current state

10424:   Notes:
10425:     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10426:          different matrices

10428:     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix

10430:     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.

10432:   Level: intermediate

10434: .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10435: @*/
10436: PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10437: {
10439:   *state = mat->nonzerostate;
10440:   return 0;
10441: }

10443: /*@
10444:       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10445:                  matrices from each processor

10447:     Collective

10449:    Input Parameters:
10450: +    comm - the communicators the parallel matrix will live on
10451: .    seqmat - the input sequential matrices
10452: .    n - number of local columns (or `PETSC_DECIDE`)
10453: -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`

10455:    Output Parameter:
10456: .    mpimat - the parallel matrix generated

10458:     Level: developer

10460:    Note:
10461:     The number of columns of the matrix in EACH processor MUST be the same.

10463: .seealso: `Mat`
10464: @*/
10465: PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10466: {
10467:   PetscMPIInt size;

10469:   MPI_Comm_size(comm, &size);
10470:   if (size == 1) {
10471:     if (reuse == MAT_INITIAL_MATRIX) {
10472:       MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat);
10473:     } else {
10474:       MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN);
10475:     }
10476:     return 0;
10477:   }


10481:   PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0);
10482:   (*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat);
10483:   PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0);
10484:   return 0;
10485: }

10487: /*@
10488:      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.

10490:     Collective on A

10492:    Input Parameters:
10493: +    A   - the matrix to create subdomains from
10494: -    N   - requested number of subdomains

10496:    Output Parameters:
10497: +    n   - number of subdomains resulting on this rank
10498: -    iss - `IS` list with indices of subdomains on this rank

10500:     Level: advanced

10502:     Note:
10503:     The number of subdomains must be smaller than the communicator size

10505: .seealso: `Mat`, `IS`
10506: @*/
10507: PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10508: {
10509:   MPI_Comm    comm, subcomm;
10510:   PetscMPIInt size, rank, color;
10511:   PetscInt    rstart, rend, k;

10513:   PetscObjectGetComm((PetscObject)A, &comm);
10514:   MPI_Comm_size(comm, &size);
10515:   MPI_Comm_rank(comm, &rank);
10517:   *n    = 1;
10518:   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10519:   color = rank / k;
10520:   MPI_Comm_split(comm, color, rank, &subcomm);
10521:   PetscMalloc1(1, iss);
10522:   MatGetOwnershipRange(A, &rstart, &rend);
10523:   ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]);
10524:   MPI_Comm_free(&subcomm);
10525:   return 0;
10526: }

10528: /*@
10529:    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.

10531:    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10532:    If they are not the same, uses `MatMatMatMult()`.

10534:    Once the coarse grid problem is constructed, correct for interpolation operators
10535:    that are not of full rank, which can legitimately happen in the case of non-nested
10536:    geometric multigrid.

10538:    Input Parameters:
10539: +  restrct - restriction operator
10540: .  dA - fine grid matrix
10541: .  interpolate - interpolation operator
10542: .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10543: -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate

10545:    Output Parameters:
10546: .  A - the Galerkin coarse matrix

10548:    Options Database Key:
10549: .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used

10551:    Level: developer

10553: .seealso: `MatPtAP()`, `MatMatMatMult()`
10554: @*/
10555: PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10556: {
10557:   IS  zerorows;
10558:   Vec diag;

10561:   /* Construct the coarse grid matrix */
10562:   if (interpolate == restrct) {
10563:     MatPtAP(dA, interpolate, reuse, fill, A);
10564:   } else {
10565:     MatMatMatMult(restrct, dA, interpolate, reuse, fill, A);
10566:   }

10568:   /* If the interpolation matrix is not of full rank, A will have zero rows.
10569:      This can legitimately happen in the case of non-nested geometric multigrid.
10570:      In that event, we set the rows of the matrix to the rows of the identity,
10571:      ignoring the equations (as the RHS will also be zero). */

10573:   MatFindZeroRows(*A, &zerorows);

10575:   if (zerorows != NULL) { /* if there are any zero rows */
10576:     MatCreateVecs(*A, &diag, NULL);
10577:     MatGetDiagonal(*A, diag);
10578:     VecISSet(diag, zerorows, 1.0);
10579:     MatDiagonalSet(*A, diag, INSERT_VALUES);
10580:     VecDestroy(&diag);
10581:     ISDestroy(&zerorows);
10582:   }
10583:   return 0;
10584: }

10586: /*@C
10587:     MatSetOperation - Allows user to set a matrix operation for any matrix type

10589:    Logically Collective on mat

10591:     Input Parameters:
10592: +   mat - the matrix
10593: .   op - the name of the operation
10594: -   f - the function that provides the operation

10596:    Level: developer

10598:     Usage:
10599: $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10600: $      MatCreateXXX(comm,...&A;
10601: $      MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult;

10603:     Notes:
10604:     See the file include/petscmat.h for a complete list of matrix
10605:     operations, which all have the form MATOP_<OPERATION>, where
10606:     <OPERATION> is the name (in all capital letters) of the
10607:     user interface routine (e.g., MatMult() -> MATOP_MULT).

10609:     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10610:     sequence as the usual matrix interface routines, since they
10611:     are intended to be accessed via the usual matrix interface
10612:     routines, e.g.,
10613: $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)

10615:     In particular each function MUST return an error code of 0 on success and
10616:     nonzero on failure.

10618:     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.

10620: .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10621: @*/
10622: PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10623: {
10625:   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10626:   (((void (**)(void))mat->ops)[op]) = f;
10627:   return 0;
10628: }

10630: /*@C
10631:     MatGetOperation - Gets a matrix operation for any matrix type.

10633:     Not Collective

10635:     Input Parameters:
10636: +   mat - the matrix
10637: -   op - the name of the operation

10639:     Output Parameter:
10640: .   f - the function that provides the operation

10642:     Level: developer

10644:     Usage:
10645: $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10646: $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);

10648:     Notes:
10649:     See the file include/petscmat.h for a complete list of matrix
10650:     operations, which all have the form MATOP_<OPERATION>, where
10651:     <OPERATION> is the name (in all capital letters) of the
10652:     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).

10654:     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.

10656: .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10657: @*/
10658: PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10659: {
10661:   *f = (((void (**)(void))mat->ops)[op]);
10662:   return 0;
10663: }

10665: /*@
10666:     MatHasOperation - Determines whether the given matrix supports the particular operation.

10668:    Not Collective

10670:    Input Parameters:
10671: +  mat - the matrix
10672: -  op - the operation, for example, `MATOP_GET_DIAGONAL`

10674:    Output Parameter:
10675: .  has - either `PETSC_TRUE` or `PETSC_FALSE`

10677:    Level: advanced

10679:    Note:
10680:    See the file include/petscmat.h for a complete list of matrix
10681:    operations, which all have the form MATOP_<OPERATION>, where
10682:    <OPERATION> is the name (in all capital letters) of the
10683:    user-level routine.  E.g., `MatNorm()` -> `MATOP_NORM`.

10685: .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10686: @*/
10687: PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10688: {
10691:   if (mat->ops->hasoperation) {
10692:     PetscUseTypeMethod(mat, hasoperation, op, has);
10693:   } else {
10694:     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10695:     else {
10696:       *has = PETSC_FALSE;
10697:       if (op == MATOP_CREATE_SUBMATRIX) {
10698:         PetscMPIInt size;

10700:         MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
10701:         if (size == 1) MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has);
10702:       }
10703:     }
10704:   }
10705:   return 0;
10706: }

10708: /*@
10709:     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent

10711:    Collective on mat

10713:    Input Parameters:
10714: .  mat - the matrix

10716:    Output Parameter:
10717: .  cong - either `PETSC_TRUE` or `PETSC_FALSE`

10719:    Level: beginner

10721: .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10722: @*/
10723: PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10724: {
10728:   if (!mat->rmap || !mat->cmap) {
10729:     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10730:     return 0;
10731:   }
10732:   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10733:     PetscLayoutSetUp(mat->rmap);
10734:     PetscLayoutSetUp(mat->cmap);
10735:     PetscLayoutCompare(mat->rmap, mat->cmap, cong);
10736:     if (*cong) mat->congruentlayouts = 1;
10737:     else mat->congruentlayouts = 0;
10738:   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10739:   return 0;
10740: }

10742: PetscErrorCode MatSetInf(Mat A)
10743: {
10744:   PetscUseTypeMethod(A, setinf);
10745:   return 0;
10746: }

10748: /*C
10749:    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
10750:    and possibly removes small values from the graph structure.

10752:    Collective on mat

10754:    Input Parameters:
10755: +  A - the matrix
10756: .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
10757: .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
10758: -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value

10760:    Output Parameter:
10761: .  graph - the resulting graph

10763:    Level: advanced

10765: .seealso: `MatCreate()`, `PCGAMG`
10766: */
10767: PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
10768: {
10772:   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
10773:   return 0;
10774: }