1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_CreateGraph; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU; 43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 48 49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 50 51 /*@ 52 MatSetRandom - Sets all components of a matrix to random numbers. 53 54 Logically Collective 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 59 it will create one internally. 60 61 Example: 62 .vb 63 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 64 MatSetRandom(x,rctx); 65 PetscRandomDestroy(rctx); 66 .ve 67 68 Level: intermediate 69 70 Notes: 71 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 72 73 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 74 75 It generates an error if used on unassembled sparse matrices that have not been preallocated. 76 77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 78 @*/ 79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 80 { 81 PetscRandom randObj = NULL; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 85 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 86 PetscValidType(x, 1); 87 MatCheckPreallocated(x, 1); 88 89 if (!rctx) { 90 MPI_Comm comm; 91 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 92 PetscCall(PetscRandomCreate(comm, &randObj)); 93 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 94 PetscCall(PetscRandomSetFromOptions(randObj)); 95 rctx = randObj; 96 } 97 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 98 PetscUseTypeMethod(x, setrandom, rctx); 99 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 100 101 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 103 PetscCall(PetscRandomDestroy(&randObj)); 104 PetscFunctionReturn(PETSC_SUCCESS); 105 } 106 107 /*@ 108 MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type 109 110 Logically Collective 111 112 Input Parameter: 113 . A - A matrix in unassembled, hash table form 114 115 Output Parameter: 116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()` 117 118 Example: 119 .vb 120 PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B)); 121 PetscCall(MatCopyHashToXAIJ(A, B)); 122 .ve 123 124 Level: advanced 125 126 Notes: 127 If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled 128 129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE` 130 @*/ 131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 135 PetscUseTypeMethod(A, copyhashtoxaij, B); 136 PetscFunctionReturn(PETSC_SUCCESS); 137 } 138 139 /*@ 140 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 141 142 Logically Collective 143 144 Input Parameter: 145 . mat - the factored matrix 146 147 Output Parameters: 148 + pivot - the pivot value computed 149 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 150 the share the matrix 151 152 Level: advanced 153 154 Notes: 155 This routine does not work for factorizations done with external packages. 156 157 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 158 159 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 160 161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 163 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 164 @*/ 165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 166 { 167 PetscFunctionBegin; 168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 169 PetscAssertPointer(pivot, 2); 170 PetscAssertPointer(row, 3); 171 *pivot = mat->factorerror_zeropivot_value; 172 *row = mat->factorerror_zeropivot_row; 173 PetscFunctionReturn(PETSC_SUCCESS); 174 } 175 176 /*@ 177 MatFactorGetError - gets the error code from a factorization 178 179 Logically Collective 180 181 Input Parameter: 182 . mat - the factored matrix 183 184 Output Parameter: 185 . err - the error code 186 187 Level: advanced 188 189 Note: 190 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 191 192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 193 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 194 @*/ 195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 196 { 197 PetscFunctionBegin; 198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 199 PetscAssertPointer(err, 2); 200 *err = mat->factorerrortype; 201 PetscFunctionReturn(PETSC_SUCCESS); 202 } 203 204 /*@ 205 MatFactorClearError - clears the error code in a factorization 206 207 Logically Collective 208 209 Input Parameter: 210 . mat - the factored matrix 211 212 Level: developer 213 214 Note: 215 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 216 217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 218 `MatGetErrorCode()`, `MatFactorError` 219 @*/ 220 PetscErrorCode MatFactorClearError(Mat mat) 221 { 222 PetscFunctionBegin; 223 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 224 mat->factorerrortype = MAT_FACTOR_NOERROR; 225 mat->factorerror_zeropivot_value = 0.0; 226 mat->factorerror_zeropivot_row = 0; 227 PetscFunctionReturn(PETSC_SUCCESS); 228 } 229 230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 231 { 232 Vec r, l; 233 const PetscScalar *al; 234 PetscInt i, nz, gnz, N, n, st; 235 236 PetscFunctionBegin; 237 PetscCall(MatCreateVecs(mat, &r, &l)); 238 if (!cols) { /* nonzero rows */ 239 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 240 PetscCall(MatGetSize(mat, &N, NULL)); 241 PetscCall(MatGetLocalSize(mat, &n, NULL)); 242 PetscCall(VecSet(l, 0.0)); 243 PetscCall(VecSetRandom(r, NULL)); 244 PetscCall(MatMult(mat, r, l)); 245 PetscCall(VecGetArrayRead(l, &al)); 246 } else { /* nonzero columns */ 247 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 248 PetscCall(MatGetSize(mat, NULL, &N)); 249 PetscCall(MatGetLocalSize(mat, NULL, &n)); 250 PetscCall(VecSet(r, 0.0)); 251 PetscCall(VecSetRandom(l, NULL)); 252 PetscCall(MatMultTranspose(mat, l, r)); 253 PetscCall(VecGetArrayRead(r, &al)); 254 } 255 if (tol <= 0.0) { 256 for (i = 0, nz = 0; i < n; i++) 257 if (al[i] != 0.0) nz++; 258 } else { 259 for (i = 0, nz = 0; i < n; i++) 260 if (PetscAbsScalar(al[i]) > tol) nz++; 261 } 262 PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 263 if (gnz != N) { 264 PetscInt *nzr; 265 PetscCall(PetscMalloc1(nz, &nzr)); 266 if (nz) { 267 if (tol < 0) { 268 for (i = 0, nz = 0; i < n; i++) 269 if (al[i] != 0.0) nzr[nz++] = i + st; 270 } else { 271 for (i = 0, nz = 0; i < n; i++) 272 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 273 } 274 } 275 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 276 } else *nonzero = NULL; 277 if (!cols) { /* nonzero rows */ 278 PetscCall(VecRestoreArrayRead(l, &al)); 279 } else { 280 PetscCall(VecRestoreArrayRead(r, &al)); 281 } 282 PetscCall(VecDestroy(&l)); 283 PetscCall(VecDestroy(&r)); 284 PetscFunctionReturn(PETSC_SUCCESS); 285 } 286 287 /*@ 288 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 289 290 Input Parameter: 291 . mat - the matrix 292 293 Output Parameter: 294 . keptrows - the rows that are not completely zero 295 296 Level: intermediate 297 298 Note: 299 `keptrows` is set to `NULL` if all rows are nonzero. 300 301 Developer Note: 302 If `keptrows` is not `NULL`, it must be sorted. 303 304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 305 @*/ 306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 307 { 308 PetscFunctionBegin; 309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 310 PetscValidType(mat, 1); 311 PetscAssertPointer(keptrows, 2); 312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 313 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 314 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 315 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 316 if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE)); 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatFindZeroRows - Locate all rows that are completely zero in the matrix 322 323 Input Parameter: 324 . mat - the matrix 325 326 Output Parameter: 327 . zerorows - the rows that are completely zero 328 329 Level: intermediate 330 331 Note: 332 `zerorows` is set to `NULL` if no rows are zero. 333 334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 335 @*/ 336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 337 { 338 IS keptrows; 339 PetscInt m, n; 340 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 343 PetscValidType(mat, 1); 344 PetscAssertPointer(zerorows, 2); 345 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 346 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 347 In keeping with this convention, we set zerorows to NULL if there are no zero 348 rows. */ 349 if (keptrows == NULL) { 350 *zerorows = NULL; 351 } else { 352 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 353 PetscCall(ISComplement(keptrows, m, n, zerorows)); 354 PetscCall(ISDestroy(&keptrows)); 355 } 356 PetscFunctionReturn(PETSC_SUCCESS); 357 } 358 359 /*@ 360 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 361 362 Not Collective 363 364 Input Parameter: 365 . A - the matrix 366 367 Output Parameter: 368 . a - the diagonal part (which is a SEQUENTIAL matrix) 369 370 Level: advanced 371 372 Notes: 373 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 374 375 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 376 377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 378 @*/ 379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 380 { 381 PetscFunctionBegin; 382 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 383 PetscValidType(A, 1); 384 PetscAssertPointer(a, 2); 385 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 386 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 387 else { 388 PetscMPIInt size; 389 390 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 391 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 392 *a = A; 393 } 394 PetscFunctionReturn(PETSC_SUCCESS); 395 } 396 397 /*@ 398 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 399 400 Collective 401 402 Input Parameter: 403 . mat - the matrix 404 405 Output Parameter: 406 . trace - the sum of the diagonal entries 407 408 Level: advanced 409 410 .seealso: [](ch_matrices), `Mat` 411 @*/ 412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 413 { 414 Vec diag; 415 416 PetscFunctionBegin; 417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 418 PetscAssertPointer(trace, 2); 419 PetscCall(MatCreateVecs(mat, &diag, NULL)); 420 PetscCall(MatGetDiagonal(mat, diag)); 421 PetscCall(VecSum(diag, trace)); 422 PetscCall(VecDestroy(&diag)); 423 PetscFunctionReturn(PETSC_SUCCESS); 424 } 425 426 /*@ 427 MatRealPart - Zeros out the imaginary part of the matrix 428 429 Logically Collective 430 431 Input Parameter: 432 . mat - the matrix 433 434 Level: advanced 435 436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 437 @*/ 438 PetscErrorCode MatRealPart(Mat mat) 439 { 440 PetscFunctionBegin; 441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 442 PetscValidType(mat, 1); 443 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 444 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 445 MatCheckPreallocated(mat, 1); 446 PetscUseTypeMethod(mat, realpart); 447 PetscFunctionReturn(PETSC_SUCCESS); 448 } 449 450 /*@C 451 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 452 453 Collective 454 455 Input Parameter: 456 . mat - the matrix 457 458 Output Parameters: 459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 460 - ghosts - the global indices of the ghost points 461 462 Level: advanced 463 464 Note: 465 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 466 467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 468 @*/ 469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 470 { 471 PetscFunctionBegin; 472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 473 PetscValidType(mat, 1); 474 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 475 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 476 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 477 else { 478 if (nghosts) *nghosts = 0; 479 if (ghosts) *ghosts = NULL; 480 } 481 PetscFunctionReturn(PETSC_SUCCESS); 482 } 483 484 /*@ 485 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 486 487 Logically Collective 488 489 Input Parameter: 490 . mat - the matrix 491 492 Level: advanced 493 494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 495 @*/ 496 PetscErrorCode MatImaginaryPart(Mat mat) 497 { 498 PetscFunctionBegin; 499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 500 PetscValidType(mat, 1); 501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 503 MatCheckPreallocated(mat, 1); 504 PetscUseTypeMethod(mat, imaginarypart); 505 PetscFunctionReturn(PETSC_SUCCESS); 506 } 507 508 /*@ 509 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 510 511 Not Collective 512 513 Input Parameter: 514 . mat - the matrix 515 516 Output Parameters: 517 + missing - is any diagonal entry missing 518 - dd - first diagonal entry that is missing (optional) on this process 519 520 Level: advanced 521 522 Note: 523 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 524 525 .seealso: [](ch_matrices), `Mat` 526 @*/ 527 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 528 { 529 PetscFunctionBegin; 530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 531 PetscValidType(mat, 1); 532 PetscAssertPointer(missing, 2); 533 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 534 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 535 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 536 PetscFunctionReturn(PETSC_SUCCESS); 537 } 538 539 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 540 /*@C 541 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 542 for each row that you get to ensure that your application does 543 not bleed memory. 544 545 Not Collective 546 547 Input Parameters: 548 + mat - the matrix 549 - row - the row to get 550 551 Output Parameters: 552 + ncols - if not `NULL`, the number of nonzeros in `row` 553 . cols - if not `NULL`, the column numbers 554 - vals - if not `NULL`, the numerical values 555 556 Level: advanced 557 558 Notes: 559 This routine is provided for people who need to have direct access 560 to the structure of a matrix. We hope that we provide enough 561 high-level matrix routines that few users will need it. 562 563 `MatGetRow()` always returns 0-based column indices, regardless of 564 whether the internal representation is 0-based (default) or 1-based. 565 566 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 567 not wish to extract these quantities. 568 569 The user can only examine the values extracted with `MatGetRow()`; 570 the values CANNOT be altered. To change the matrix entries, one 571 must use `MatSetValues()`. 572 573 You can only have one call to `MatGetRow()` outstanding for a particular 574 matrix at a time, per processor. `MatGetRow()` can only obtain rows 575 associated with the given processor, it cannot get rows from the 576 other processors; for that we suggest using `MatCreateSubMatrices()`, then 577 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 578 is in the global number of rows. 579 580 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 581 582 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 583 584 Fortran Note: 585 .vb 586 PetscInt, pointer :: cols(:) 587 PetscScalar, pointer :: vals(:) 588 .ve 589 590 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 591 @*/ 592 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 593 { 594 PetscInt incols; 595 596 PetscFunctionBegin; 597 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 598 PetscValidType(mat, 1); 599 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 600 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 601 MatCheckPreallocated(mat, 1); 602 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 603 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 604 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 605 if (ncols) *ncols = incols; 606 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 607 PetscFunctionReturn(PETSC_SUCCESS); 608 } 609 610 /*@ 611 MatConjugate - replaces the matrix values with their complex conjugates 612 613 Logically Collective 614 615 Input Parameter: 616 . mat - the matrix 617 618 Level: advanced 619 620 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 621 @*/ 622 PetscErrorCode MatConjugate(Mat mat) 623 { 624 PetscFunctionBegin; 625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 626 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 627 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 628 PetscUseTypeMethod(mat, conjugate); 629 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 630 } 631 PetscFunctionReturn(PETSC_SUCCESS); 632 } 633 634 /*@C 635 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 636 637 Not Collective 638 639 Input Parameters: 640 + mat - the matrix 641 . row - the row to get 642 . ncols - the number of nonzeros 643 . cols - the columns of the nonzeros 644 - vals - if nonzero the column values 645 646 Level: advanced 647 648 Notes: 649 This routine should be called after you have finished examining the entries. 650 651 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 652 us of the array after it has been restored. If you pass `NULL`, it will 653 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 654 655 Fortran Note: 656 .vb 657 PetscInt, pointer :: cols(:) 658 PetscScalar, pointer :: vals(:) 659 .ve 660 661 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 662 @*/ 663 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 664 { 665 PetscFunctionBegin; 666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 667 if (ncols) PetscAssertPointer(ncols, 3); 668 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 669 PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 670 if (ncols) *ncols = 0; 671 if (cols) *cols = NULL; 672 if (vals) *vals = NULL; 673 PetscFunctionReturn(PETSC_SUCCESS); 674 } 675 676 /*@ 677 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 678 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 679 680 Not Collective 681 682 Input Parameter: 683 . mat - the matrix 684 685 Level: advanced 686 687 Note: 688 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. 689 690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 PetscTryTypeMethod(mat, getrowuppertriangular); 701 PetscFunctionReturn(PETSC_SUCCESS); 702 } 703 704 /*@ 705 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 706 707 Not Collective 708 709 Input Parameter: 710 . mat - the matrix 711 712 Level: advanced 713 714 Note: 715 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 716 717 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 718 @*/ 719 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 720 { 721 PetscFunctionBegin; 722 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 723 PetscValidType(mat, 1); 724 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 725 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 726 MatCheckPreallocated(mat, 1); 727 PetscTryTypeMethod(mat, restorerowuppertriangular); 728 PetscFunctionReturn(PETSC_SUCCESS); 729 } 730 731 /*@ 732 MatSetOptionsPrefix - Sets the prefix used for searching for all 733 `Mat` options in the database. 734 735 Logically Collective 736 737 Input Parameters: 738 + A - the matrix 739 - prefix - the prefix to prepend to all option names 740 741 Level: advanced 742 743 Notes: 744 A hyphen (-) must NOT be given at the beginning of the prefix name. 745 The first character of all runtime options is AUTOMATICALLY the hyphen. 746 747 This is NOT used for options for the factorization of the matrix. Normally the 748 prefix is automatically passed in from the PC calling the factorization. To set 749 it directly use `MatSetOptionsPrefixFactor()` 750 751 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 752 @*/ 753 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 754 { 755 PetscFunctionBegin; 756 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 757 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 758 PetscTryMethod(A, "MatSetOptionsPrefix_C", (Mat, const char[]), (A, prefix)); 759 PetscFunctionReturn(PETSC_SUCCESS); 760 } 761 762 /*@ 763 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 764 for matrices created with `MatGetFactor()` 765 766 Logically Collective 767 768 Input Parameters: 769 + A - the matrix 770 - prefix - the prefix to prepend to all option names for the factored matrix 771 772 Level: developer 773 774 Notes: 775 A hyphen (-) must NOT be given at the beginning of the prefix name. 776 The first character of all runtime options is AUTOMATICALLY the hyphen. 777 778 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 779 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 780 781 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 782 @*/ 783 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 784 { 785 PetscFunctionBegin; 786 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 787 if (prefix) { 788 PetscAssertPointer(prefix, 2); 789 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 790 if (prefix != A->factorprefix) { 791 PetscCall(PetscFree(A->factorprefix)); 792 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 793 } 794 } else PetscCall(PetscFree(A->factorprefix)); 795 PetscFunctionReturn(PETSC_SUCCESS); 796 } 797 798 /*@ 799 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 800 for matrices created with `MatGetFactor()` 801 802 Logically Collective 803 804 Input Parameters: 805 + A - the matrix 806 - prefix - the prefix to prepend to all option names for the factored matrix 807 808 Level: developer 809 810 Notes: 811 A hyphen (-) must NOT be given at the beginning of the prefix name. 812 The first character of all runtime options is AUTOMATICALLY the hyphen. 813 814 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 815 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 816 817 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 818 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 819 `MatSetOptionsPrefix()` 820 @*/ 821 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 822 { 823 size_t len1, len2, new_len; 824 825 PetscFunctionBegin; 826 PetscValidHeader(A, 1); 827 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 828 if (!A->factorprefix) { 829 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 830 PetscFunctionReturn(PETSC_SUCCESS); 831 } 832 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 833 834 PetscCall(PetscStrlen(A->factorprefix, &len1)); 835 PetscCall(PetscStrlen(prefix, &len2)); 836 new_len = len1 + len2 + 1; 837 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 838 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 839 PetscFunctionReturn(PETSC_SUCCESS); 840 } 841 842 /*@ 843 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 844 matrix options in the database. 845 846 Logically Collective 847 848 Input Parameters: 849 + A - the matrix 850 - prefix - the prefix to prepend to all option names 851 852 Level: advanced 853 854 Note: 855 A hyphen (-) must NOT be given at the beginning of the prefix name. 856 The first character of all runtime options is AUTOMATICALLY the hyphen. 857 858 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 859 @*/ 860 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 861 { 862 PetscFunctionBegin; 863 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 864 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 865 PetscTryMethod(A, "MatAppendOptionsPrefix_C", (Mat, const char[]), (A, prefix)); 866 PetscFunctionReturn(PETSC_SUCCESS); 867 } 868 869 /*@ 870 MatGetOptionsPrefix - Gets the prefix used for searching for all 871 matrix options in the database. 872 873 Not Collective 874 875 Input Parameter: 876 . A - the matrix 877 878 Output Parameter: 879 . prefix - pointer to the prefix string used 880 881 Level: advanced 882 883 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 884 @*/ 885 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 886 { 887 PetscFunctionBegin; 888 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 889 PetscAssertPointer(prefix, 2); 890 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 891 PetscFunctionReturn(PETSC_SUCCESS); 892 } 893 894 /*@ 895 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 896 897 Not Collective 898 899 Input Parameter: 900 . A - the matrix 901 902 Output Parameter: 903 . state - the object state 904 905 Level: advanced 906 907 Note: 908 Object state is an integer which gets increased every time 909 the object is changed. By saving and later querying the object state 910 one can determine whether information about the object is still current. 911 912 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 913 914 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 915 @*/ 916 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 917 { 918 PetscFunctionBegin; 919 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 920 PetscAssertPointer(state, 2); 921 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 922 PetscFunctionReturn(PETSC_SUCCESS); 923 } 924 925 /*@ 926 MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 927 928 Collective 929 930 Input Parameter: 931 . A - the matrix 932 933 Level: beginner 934 935 Notes: 936 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 937 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 938 makes all of the preallocation space available 939 940 Current values in the matrix are lost in this call 941 942 Currently only supported for `MATAIJ` matrices. 943 944 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 945 @*/ 946 PetscErrorCode MatResetPreallocation(Mat A) 947 { 948 PetscFunctionBegin; 949 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 950 PetscValidType(A, 1); 951 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 952 PetscFunctionReturn(PETSC_SUCCESS); 953 } 954 955 /*@ 956 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 957 958 Collective 959 960 Input Parameter: 961 . A - the matrix 962 963 Level: intermediate 964 965 Notes: 966 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 967 968 Currently only supported for `MATAIJ` matrices. 969 970 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 971 @*/ 972 PetscErrorCode MatResetHash(Mat A) 973 { 974 PetscFunctionBegin; 975 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 976 PetscValidType(A, 1); 977 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset to hash state after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 978 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 979 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 980 /* These flags are used to determine whether certain setups occur */ 981 A->was_assembled = PETSC_FALSE; 982 A->assembled = PETSC_FALSE; 983 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 984 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 985 PetscFunctionReturn(PETSC_SUCCESS); 986 } 987 988 /*@ 989 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 990 991 Collective 992 993 Input Parameter: 994 . A - the matrix 995 996 Level: advanced 997 998 Notes: 999 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 1000 setting values in the matrix. 1001 1002 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 1003 1004 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 1005 @*/ 1006 PetscErrorCode MatSetUp(Mat A) 1007 { 1008 PetscFunctionBegin; 1009 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1010 if (!((PetscObject)A)->type_name) { 1011 PetscMPIInt size; 1012 1013 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1014 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 1015 } 1016 if (!A->preallocated) PetscTryTypeMethod(A, setup); 1017 PetscCall(PetscLayoutSetUp(A->rmap)); 1018 PetscCall(PetscLayoutSetUp(A->cmap)); 1019 A->preallocated = PETSC_TRUE; 1020 PetscFunctionReturn(PETSC_SUCCESS); 1021 } 1022 1023 #if defined(PETSC_HAVE_SAWS) 1024 #include <petscviewersaws.h> 1025 #endif 1026 1027 /* 1028 If threadsafety is on extraneous matrices may be printed 1029 1030 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1031 */ 1032 #if !defined(PETSC_HAVE_THREADSAFETY) 1033 static PetscInt insidematview = 0; 1034 #endif 1035 1036 /*@ 1037 MatViewFromOptions - View properties of the matrix based on options set in the options database 1038 1039 Collective 1040 1041 Input Parameters: 1042 + A - the matrix 1043 . obj - optional additional object that provides the options prefix to use 1044 - name - command line option 1045 1046 Options Database Key: 1047 . -mat_view [viewertype]:... - the viewer and its options 1048 1049 Level: intermediate 1050 1051 Note: 1052 .vb 1053 If no value is provided ascii:stdout is used 1054 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1055 for example ascii::ascii_info prints just the information about the object not all details 1056 unless :append is given filename opens in write mode, overwriting what was already there 1057 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1058 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1059 socket[:port] defaults to the standard output port 1060 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1061 .ve 1062 1063 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1064 @*/ 1065 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1066 { 1067 PetscFunctionBegin; 1068 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1069 #if !defined(PETSC_HAVE_THREADSAFETY) 1070 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1071 #endif 1072 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1073 PetscFunctionReturn(PETSC_SUCCESS); 1074 } 1075 1076 /*@ 1077 MatView - display information about a matrix in a variety ways 1078 1079 Collective on viewer 1080 1081 Input Parameters: 1082 + mat - the matrix 1083 - viewer - visualization context 1084 1085 Options Database Keys: 1086 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1087 . -mat_view ::ascii_info_detail - Prints more detailed info 1088 . -mat_view - Prints matrix in ASCII format 1089 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1090 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1091 . -display <name> - Sets display name (default is host) 1092 . -draw_pause <sec> - Sets number of seconds to pause after display 1093 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1094 . -viewer_socket_machine <machine> - - 1095 . -viewer_socket_port <port> - - 1096 . -mat_view binary - save matrix to file in binary format 1097 - -viewer_binary_filename <name> - - 1098 1099 Level: beginner 1100 1101 Notes: 1102 The available visualization contexts include 1103 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1104 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1105 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1106 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1107 1108 The user can open alternative visualization contexts with 1109 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1110 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1111 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1112 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1113 1114 The user can call `PetscViewerPushFormat()` to specify the output 1115 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1116 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1117 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1118 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1119 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1120 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1121 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1122 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1123 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1124 1125 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1126 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1127 1128 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1129 1130 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1131 viewer is used. 1132 1133 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1134 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1135 1136 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1137 and then use the following mouse functions. 1138 .vb 1139 left mouse: zoom in 1140 middle mouse: zoom out 1141 right mouse: continue with the simulation 1142 .ve 1143 1144 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1145 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1146 @*/ 1147 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1148 { 1149 PetscInt rows, cols, rbs, cbs; 1150 PetscBool isascii, isstring, issaws; 1151 PetscViewerFormat format; 1152 PetscMPIInt size; 1153 1154 PetscFunctionBegin; 1155 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1156 PetscValidType(mat, 1); 1157 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1158 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1159 1160 PetscCall(PetscViewerGetFormat(viewer, &format)); 1161 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1162 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1163 1164 #if !defined(PETSC_HAVE_THREADSAFETY) 1165 insidematview++; 1166 #endif 1167 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1168 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1169 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1170 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1171 1172 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1173 if (isascii) { 1174 if (!mat->preallocated) { 1175 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1176 #if !defined(PETSC_HAVE_THREADSAFETY) 1177 insidematview--; 1178 #endif 1179 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1180 PetscFunctionReturn(PETSC_SUCCESS); 1181 } 1182 if (!mat->assembled) { 1183 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1184 #if !defined(PETSC_HAVE_THREADSAFETY) 1185 insidematview--; 1186 #endif 1187 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1188 PetscFunctionReturn(PETSC_SUCCESS); 1189 } 1190 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1191 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1192 MatNullSpace nullsp, transnullsp; 1193 1194 PetscCall(PetscViewerASCIIPushTab(viewer)); 1195 PetscCall(MatGetSize(mat, &rows, &cols)); 1196 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1197 if (rbs != 1 || cbs != 1) { 1198 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "%s\n", rows, cols, rbs, cbs, mat->bsizes ? " variable blocks set" : "")); 1199 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1200 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1201 if (mat->factortype) { 1202 MatSolverType solver; 1203 PetscCall(MatFactorGetSolverType(mat, &solver)); 1204 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1205 } 1206 if (mat->ops->getinfo) { 1207 PetscBool is_constant_or_diagonal; 1208 1209 // Don't print nonzero information for constant or diagonal matrices, it just adds noise to the output 1210 PetscCall(PetscObjectTypeCompareAny((PetscObject)mat, &is_constant_or_diagonal, MATCONSTANTDIAGONAL, MATDIAGONAL, "")); 1211 if (!is_constant_or_diagonal) { 1212 MatInfo info; 1213 1214 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1215 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1216 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1217 } 1218 } 1219 PetscCall(MatGetNullSpace(mat, &nullsp)); 1220 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1221 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1222 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1223 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1224 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1225 PetscCall(PetscViewerASCIIPushTab(viewer)); 1226 PetscCall(MatProductView(mat, viewer)); 1227 PetscCall(PetscViewerASCIIPopTab(viewer)); 1228 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1229 IS tmp; 1230 1231 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1232 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1233 PetscCall(PetscViewerASCIIPushTab(viewer)); 1234 PetscCall(ISView(tmp, viewer)); 1235 PetscCall(PetscViewerASCIIPopTab(viewer)); 1236 PetscCall(ISDestroy(&tmp)); 1237 } 1238 } 1239 } else if (issaws) { 1240 #if defined(PETSC_HAVE_SAWS) 1241 PetscMPIInt rank; 1242 1243 PetscCall(PetscObjectName((PetscObject)mat)); 1244 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1245 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1246 #endif 1247 } else if (isstring) { 1248 const char *type; 1249 PetscCall(MatGetType(mat, &type)); 1250 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1251 PetscTryTypeMethod(mat, view, viewer); 1252 } 1253 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1254 PetscCall(PetscViewerASCIIPushTab(viewer)); 1255 PetscUseTypeMethod(mat, viewnative, viewer); 1256 PetscCall(PetscViewerASCIIPopTab(viewer)); 1257 } else if (mat->ops->view) { 1258 PetscCall(PetscViewerASCIIPushTab(viewer)); 1259 PetscUseTypeMethod(mat, view, viewer); 1260 PetscCall(PetscViewerASCIIPopTab(viewer)); 1261 } 1262 if (isascii) { 1263 PetscCall(PetscViewerGetFormat(viewer, &format)); 1264 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1265 } 1266 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1267 #if !defined(PETSC_HAVE_THREADSAFETY) 1268 insidematview--; 1269 #endif 1270 PetscFunctionReturn(PETSC_SUCCESS); 1271 } 1272 1273 #if defined(PETSC_USE_DEBUG) 1274 #include <../src/sys/totalview/tv_data_display.h> 1275 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1276 { 1277 TV_add_row("Local rows", "int", &mat->rmap->n); 1278 TV_add_row("Local columns", "int", &mat->cmap->n); 1279 TV_add_row("Global rows", "int", &mat->rmap->N); 1280 TV_add_row("Global columns", "int", &mat->cmap->N); 1281 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1282 return TV_format_OK; 1283 } 1284 #endif 1285 1286 /*@ 1287 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1288 with `MatView()`. The matrix format is determined from the options database. 1289 Generates a parallel MPI matrix if the communicator has more than one 1290 processor. The default matrix type is `MATAIJ`. 1291 1292 Collective 1293 1294 Input Parameters: 1295 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1296 or some related function before a call to `MatLoad()` 1297 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1298 1299 Options Database Key: 1300 . -matload_block_size <bs> - set block size 1301 1302 Level: beginner 1303 1304 Notes: 1305 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1306 `Mat` before calling this routine if you wish to set it from the options database. 1307 1308 `MatLoad()` automatically loads into the options database any options 1309 given in the file filename.info where filename is the name of the file 1310 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1311 file will be ignored if you use the -viewer_binary_skip_info option. 1312 1313 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1314 sets the default matrix type AIJ and sets the local and global sizes. 1315 If type and/or size is already set, then the same are used. 1316 1317 In parallel, each processor can load a subset of rows (or the 1318 entire matrix). This routine is especially useful when a large 1319 matrix is stored on disk and only part of it is desired on each 1320 processor. For example, a parallel solver may access only some of 1321 the rows from each processor. The algorithm used here reads 1322 relatively small blocks of data rather than reading the entire 1323 matrix and then subsetting it. 1324 1325 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1326 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1327 or the sequence like 1328 .vb 1329 `PetscViewer` v; 1330 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1331 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1332 `PetscViewerSetFromOptions`(v); 1333 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1334 `PetscViewerFileSetName`(v,"datafile"); 1335 .ve 1336 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1337 .vb 1338 -viewer_type {binary, hdf5} 1339 .ve 1340 1341 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1342 and src/mat/tutorials/ex10.c with the second approach. 1343 1344 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1345 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1346 Multiple objects, both matrices and vectors, can be stored within the same file. 1347 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1348 1349 Most users should not need to know the details of the binary storage 1350 format, since `MatLoad()` and `MatView()` completely hide these details. 1351 But for anyone who is interested, the standard binary matrix storage 1352 format is 1353 1354 .vb 1355 PetscInt MAT_FILE_CLASSID 1356 PetscInt number of rows 1357 PetscInt number of columns 1358 PetscInt total number of nonzeros 1359 PetscInt *number nonzeros in each row 1360 PetscInt *column indices of all nonzeros (starting index is zero) 1361 PetscScalar *values of all nonzeros 1362 .ve 1363 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1364 stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this 1365 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1366 1367 PETSc automatically does the byte swapping for 1368 machines that store the bytes reversed. Thus if you write your own binary 1369 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1370 and `PetscBinaryWrite()` to see how this may be done. 1371 1372 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1373 Each processor's chunk is loaded independently by its owning MPI process. 1374 Multiple objects, both matrices and vectors, can be stored within the same file. 1375 They are looked up by their PetscObject name. 1376 1377 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1378 by default the same structure and naming of the AIJ arrays and column count 1379 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1380 .vb 1381 save example.mat A b -v7.3 1382 .ve 1383 can be directly read by this routine (see Reference 1 for details). 1384 1385 Depending on your MATLAB version, this format might be a default, 1386 otherwise you can set it as default in Preferences. 1387 1388 Unless -nocompression flag is used to save the file in MATLAB, 1389 PETSc must be configured with ZLIB package. 1390 1391 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1392 1393 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1394 1395 Corresponding `MatView()` is not yet implemented. 1396 1397 The loaded matrix is actually a transpose of the original one in MATLAB, 1398 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1399 With this format, matrix is automatically transposed by PETSc, 1400 unless the matrix is marked as SPD or symmetric 1401 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1402 1403 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1404 1405 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1406 @*/ 1407 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1408 { 1409 PetscBool flg; 1410 1411 PetscFunctionBegin; 1412 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1413 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1414 1415 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1416 1417 flg = PETSC_FALSE; 1418 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1419 if (flg) { 1420 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1421 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1422 } 1423 flg = PETSC_FALSE; 1424 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1425 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1426 1427 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1428 PetscUseTypeMethod(mat, load, viewer); 1429 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1430 PetscFunctionReturn(PETSC_SUCCESS); 1431 } 1432 1433 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1434 { 1435 Mat_Redundant *redund = *redundant; 1436 1437 PetscFunctionBegin; 1438 if (redund) { 1439 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1440 PetscCall(ISDestroy(&redund->isrow)); 1441 PetscCall(ISDestroy(&redund->iscol)); 1442 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1443 } else { 1444 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1445 PetscCall(PetscFree(redund->sbuf_j)); 1446 PetscCall(PetscFree(redund->sbuf_a)); 1447 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1448 PetscCall(PetscFree(redund->rbuf_j[i])); 1449 PetscCall(PetscFree(redund->rbuf_a[i])); 1450 } 1451 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1452 } 1453 1454 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1455 PetscCall(PetscFree(redund)); 1456 } 1457 PetscFunctionReturn(PETSC_SUCCESS); 1458 } 1459 1460 /*@ 1461 MatDestroy - Frees space taken by a matrix. 1462 1463 Collective 1464 1465 Input Parameter: 1466 . A - the matrix 1467 1468 Level: beginner 1469 1470 Developer Note: 1471 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1472 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1473 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1474 if changes are needed here. 1475 1476 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1477 @*/ 1478 PetscErrorCode MatDestroy(Mat *A) 1479 { 1480 PetscFunctionBegin; 1481 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1482 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1483 if (--((PetscObject)*A)->refct > 0) { 1484 *A = NULL; 1485 PetscFunctionReturn(PETSC_SUCCESS); 1486 } 1487 1488 /* if memory was published with SAWs then destroy it */ 1489 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1490 PetscTryTypeMethod(*A, destroy); 1491 1492 PetscCall(PetscFree((*A)->factorprefix)); 1493 PetscCall(PetscFree((*A)->defaultvectype)); 1494 PetscCall(PetscFree((*A)->defaultrandtype)); 1495 PetscCall(PetscFree((*A)->bsizes)); 1496 PetscCall(PetscFree((*A)->solvertype)); 1497 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1498 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1499 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1500 PetscCall(MatProductClear(*A)); 1501 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1502 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1503 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1504 PetscCall(MatDestroy(&(*A)->schur)); 1505 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1506 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1507 PetscCall(PetscHeaderDestroy(A)); 1508 PetscFunctionReturn(PETSC_SUCCESS); 1509 } 1510 1511 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1512 /*@ 1513 MatSetValues - Inserts or adds a block of values into a matrix. 1514 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1515 MUST be called after all calls to `MatSetValues()` have been completed. 1516 1517 Not Collective 1518 1519 Input Parameters: 1520 + mat - the matrix 1521 . v - a logically two-dimensional array of values 1522 . m - the number of rows 1523 . idxm - the global indices of the rows 1524 . n - the number of columns 1525 . idxn - the global indices of the columns 1526 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1527 1528 Level: beginner 1529 1530 Notes: 1531 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1532 1533 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1534 options cannot be mixed without intervening calls to the assembly 1535 routines. 1536 1537 `MatSetValues()` uses 0-based row and column numbers in Fortran 1538 as well as in C. 1539 1540 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1541 simply ignored. This allows easily inserting element stiffness matrices 1542 with homogeneous Dirichlet boundary conditions that you don't want represented 1543 in the matrix. 1544 1545 Efficiency Alert: 1546 The routine `MatSetValuesBlocked()` may offer much better efficiency 1547 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1548 1549 Fortran Notes: 1550 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1551 .vb 1552 call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 1553 .ve 1554 1555 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1556 1557 Developer Note: 1558 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1559 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1560 1561 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1562 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1563 @*/ 1564 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1565 { 1566 PetscFunctionBeginHot; 1567 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1568 PetscValidType(mat, 1); 1569 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1570 PetscAssertPointer(idxm, 3); 1571 PetscAssertPointer(idxn, 5); 1572 MatCheckPreallocated(mat, 1); 1573 1574 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1575 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1576 1577 if (PetscDefined(USE_DEBUG)) { 1578 PetscInt i, j; 1579 1580 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1581 if (v) { 1582 for (i = 0; i < m; i++) { 1583 for (j = 0; j < n; j++) { 1584 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1585 #if defined(PETSC_USE_COMPLEX) 1586 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]); 1587 #else 1588 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]); 1589 #endif 1590 } 1591 } 1592 } 1593 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1594 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1595 } 1596 1597 if (mat->assembled) { 1598 mat->was_assembled = PETSC_TRUE; 1599 mat->assembled = PETSC_FALSE; 1600 } 1601 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1602 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1603 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1604 PetscFunctionReturn(PETSC_SUCCESS); 1605 } 1606 1607 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1608 /*@ 1609 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1610 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1611 MUST be called after all calls to `MatSetValues()` have been completed. 1612 1613 Not Collective 1614 1615 Input Parameters: 1616 + mat - the matrix 1617 . v - a logically two-dimensional array of values 1618 . ism - the rows to provide 1619 . isn - the columns to provide 1620 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1621 1622 Level: beginner 1623 1624 Notes: 1625 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1626 1627 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1628 options cannot be mixed without intervening calls to the assembly 1629 routines. 1630 1631 `MatSetValues()` uses 0-based row and column numbers in Fortran 1632 as well as in C. 1633 1634 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1635 simply ignored. This allows easily inserting element stiffness matrices 1636 with homogeneous Dirichlet boundary conditions that you don't want represented 1637 in the matrix. 1638 1639 Efficiency Alert: 1640 The routine `MatSetValuesBlocked()` may offer much better efficiency 1641 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1642 1643 This is currently not optimized for any particular `ISType` 1644 1645 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1646 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1647 @*/ 1648 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1649 { 1650 PetscInt m, n; 1651 const PetscInt *rows, *cols; 1652 1653 PetscFunctionBeginHot; 1654 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1655 PetscCall(ISGetIndices(ism, &rows)); 1656 PetscCall(ISGetIndices(isn, &cols)); 1657 PetscCall(ISGetLocalSize(ism, &m)); 1658 PetscCall(ISGetLocalSize(isn, &n)); 1659 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1660 PetscCall(ISRestoreIndices(ism, &rows)); 1661 PetscCall(ISRestoreIndices(isn, &cols)); 1662 PetscFunctionReturn(PETSC_SUCCESS); 1663 } 1664 1665 /*@ 1666 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1667 values into a matrix 1668 1669 Not Collective 1670 1671 Input Parameters: 1672 + mat - the matrix 1673 . row - the (block) row to set 1674 - v - a logically two-dimensional array of values 1675 1676 Level: intermediate 1677 1678 Notes: 1679 The values, `v`, are column-oriented (for the block version) and sorted 1680 1681 All the nonzero values in `row` must be provided 1682 1683 The matrix must have previously had its column indices set, likely by having been assembled. 1684 1685 `row` must belong to this MPI process 1686 1687 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1688 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1689 @*/ 1690 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1691 { 1692 PetscInt globalrow; 1693 1694 PetscFunctionBegin; 1695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1696 PetscValidType(mat, 1); 1697 PetscAssertPointer(v, 3); 1698 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1699 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1700 PetscFunctionReturn(PETSC_SUCCESS); 1701 } 1702 1703 /*@ 1704 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1705 values into a matrix 1706 1707 Not Collective 1708 1709 Input Parameters: 1710 + mat - the matrix 1711 . row - the (block) row to set 1712 - 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 1713 1714 Level: advanced 1715 1716 Notes: 1717 The values, `v`, are column-oriented for the block version. 1718 1719 All the nonzeros in `row` must be provided 1720 1721 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1722 1723 `row` must belong to this process 1724 1725 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1726 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1727 @*/ 1728 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1729 { 1730 PetscFunctionBeginHot; 1731 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1732 PetscValidType(mat, 1); 1733 MatCheckPreallocated(mat, 1); 1734 PetscAssertPointer(v, 3); 1735 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1736 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1737 mat->insertmode = INSERT_VALUES; 1738 1739 if (mat->assembled) { 1740 mat->was_assembled = PETSC_TRUE; 1741 mat->assembled = PETSC_FALSE; 1742 } 1743 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1744 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1745 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1746 PetscFunctionReturn(PETSC_SUCCESS); 1747 } 1748 1749 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1750 /*@ 1751 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1752 Using structured grid indexing 1753 1754 Not Collective 1755 1756 Input Parameters: 1757 + mat - the matrix 1758 . m - number of rows being entered 1759 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1760 . n - number of columns being entered 1761 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1762 . v - a logically two-dimensional array of values 1763 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1764 1765 Level: beginner 1766 1767 Notes: 1768 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1769 1770 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1771 options cannot be mixed without intervening calls to the assembly 1772 routines. 1773 1774 The grid coordinates are across the entire grid, not just the local portion 1775 1776 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1777 as well as in C. 1778 1779 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1780 1781 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1782 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1783 1784 The columns and rows in the stencil passed in MUST be contained within the 1785 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1786 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1787 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1788 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1789 1790 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1791 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1792 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1793 `DM_BOUNDARY_PERIODIC` boundary type. 1794 1795 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 1796 a single value per point) you can skip filling those indices. 1797 1798 Inspired by the structured grid interface to the HYPRE package 1799 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1800 1801 Efficiency Alert: 1802 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1803 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1804 1805 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1806 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1807 @*/ 1808 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1809 { 1810 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1811 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1812 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1813 1814 PetscFunctionBegin; 1815 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1816 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1817 PetscValidType(mat, 1); 1818 PetscAssertPointer(idxm, 3); 1819 PetscAssertPointer(idxn, 5); 1820 1821 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1822 jdxm = buf; 1823 jdxn = buf + m; 1824 } else { 1825 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1826 jdxm = bufm; 1827 jdxn = bufn; 1828 } 1829 for (i = 0; i < m; i++) { 1830 for (j = 0; j < 3 - sdim; j++) dxm++; 1831 tmp = *dxm++ - starts[0]; 1832 for (j = 0; j < dim - 1; j++) { 1833 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1834 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1835 } 1836 if (mat->stencil.noc) dxm++; 1837 jdxm[i] = tmp; 1838 } 1839 for (i = 0; i < n; i++) { 1840 for (j = 0; j < 3 - sdim; j++) dxn++; 1841 tmp = *dxn++ - starts[0]; 1842 for (j = 0; j < dim - 1; j++) { 1843 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1844 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1845 } 1846 if (mat->stencil.noc) dxn++; 1847 jdxn[i] = tmp; 1848 } 1849 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1850 PetscCall(PetscFree2(bufm, bufn)); 1851 PetscFunctionReturn(PETSC_SUCCESS); 1852 } 1853 1854 /*@ 1855 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1856 Using structured grid indexing 1857 1858 Not Collective 1859 1860 Input Parameters: 1861 + mat - the matrix 1862 . m - number of rows being entered 1863 . idxm - grid coordinates for matrix rows being entered 1864 . n - number of columns being entered 1865 . idxn - grid coordinates for matrix columns being entered 1866 . v - a logically two-dimensional array of values 1867 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1868 1869 Level: beginner 1870 1871 Notes: 1872 By default the values, `v`, are row-oriented and unsorted. 1873 See `MatSetOption()` for other options. 1874 1875 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1876 options cannot be mixed without intervening calls to the assembly 1877 routines. 1878 1879 The grid coordinates are across the entire grid, not just the local portion 1880 1881 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1882 as well as in C. 1883 1884 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1885 1886 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1887 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1888 1889 The columns and rows in the stencil passed in MUST be contained within the 1890 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1891 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1892 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1893 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1894 1895 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1896 simply ignored. This allows easily inserting element stiffness matrices 1897 with homogeneous Dirichlet boundary conditions that you don't want represented 1898 in the matrix. 1899 1900 Inspired by the structured grid interface to the HYPRE package 1901 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1902 1903 Fortran Note: 1904 `idxm` and `idxn` should be declared as 1905 .vb 1906 MatStencil idxm(4,m),idxn(4,n) 1907 .ve 1908 and the values inserted using 1909 .vb 1910 idxm(MatStencil_i,1) = i 1911 idxm(MatStencil_j,1) = j 1912 idxm(MatStencil_k,1) = k 1913 etc 1914 .ve 1915 1916 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1917 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1918 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1919 @*/ 1920 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1921 { 1922 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1923 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1924 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1925 1926 PetscFunctionBegin; 1927 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1928 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1929 PetscValidType(mat, 1); 1930 PetscAssertPointer(idxm, 3); 1931 PetscAssertPointer(idxn, 5); 1932 PetscAssertPointer(v, 6); 1933 1934 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1935 jdxm = buf; 1936 jdxn = buf + m; 1937 } else { 1938 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1939 jdxm = bufm; 1940 jdxn = bufn; 1941 } 1942 for (i = 0; i < m; i++) { 1943 for (j = 0; j < 3 - sdim; j++) dxm++; 1944 tmp = *dxm++ - starts[0]; 1945 for (j = 0; j < sdim - 1; j++) { 1946 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1947 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1948 } 1949 dxm++; 1950 jdxm[i] = tmp; 1951 } 1952 for (i = 0; i < n; i++) { 1953 for (j = 0; j < 3 - sdim; j++) dxn++; 1954 tmp = *dxn++ - starts[0]; 1955 for (j = 0; j < sdim - 1; j++) { 1956 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1957 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1958 } 1959 dxn++; 1960 jdxn[i] = tmp; 1961 } 1962 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1963 PetscCall(PetscFree2(bufm, bufn)); 1964 PetscFunctionReturn(PETSC_SUCCESS); 1965 } 1966 1967 /*@ 1968 MatSetStencil - Sets the grid information for setting values into a matrix via 1969 `MatSetValuesStencil()` 1970 1971 Not Collective 1972 1973 Input Parameters: 1974 + mat - the matrix 1975 . dim - dimension of the grid 1, 2, or 3 1976 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1977 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1978 - dof - number of degrees of freedom per node 1979 1980 Level: beginner 1981 1982 Notes: 1983 Inspired by the structured grid interface to the HYPRE package 1984 (www.llnl.gov/CASC/hyper) 1985 1986 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1987 user. 1988 1989 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1990 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1991 @*/ 1992 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1993 { 1994 PetscFunctionBegin; 1995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1996 PetscAssertPointer(dims, 3); 1997 PetscAssertPointer(starts, 4); 1998 1999 mat->stencil.dim = dim + (dof > 1); 2000 for (PetscInt i = 0; i < dim; i++) { 2001 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 2002 mat->stencil.starts[i] = starts[dim - i - 1]; 2003 } 2004 mat->stencil.dims[dim] = dof; 2005 mat->stencil.starts[dim] = 0; 2006 mat->stencil.noc = (PetscBool)(dof == 1); 2007 PetscFunctionReturn(PETSC_SUCCESS); 2008 } 2009 2010 /*@ 2011 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2012 2013 Not Collective 2014 2015 Input Parameters: 2016 + mat - the matrix 2017 . v - a logically two-dimensional array of values 2018 . m - the number of block rows 2019 . idxm - the global block indices 2020 . n - the number of block columns 2021 . idxn - the global block indices 2022 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2023 2024 Level: intermediate 2025 2026 Notes: 2027 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2028 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2029 2030 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2031 NOT the total number of rows/columns; for example, if the block size is 2 and 2032 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2033 The values in `idxm` would be 1 2; that is the first index for each block divided by 2034 the block size. 2035 2036 You must call `MatSetBlockSize()` when constructing this matrix (before 2037 preallocating it). 2038 2039 By default the values, `v`, are row-oriented, so the layout of 2040 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2041 2042 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2043 options cannot be mixed without intervening calls to the assembly 2044 routines. 2045 2046 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2047 as well as in C. 2048 2049 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2050 simply ignored. This allows easily inserting element stiffness matrices 2051 with homogeneous Dirichlet boundary conditions that you don't want represented 2052 in the matrix. 2053 2054 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2055 internal searching must be done to determine where to place the 2056 data in the matrix storage space. By instead inserting blocks of 2057 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2058 reduced. 2059 2060 Example: 2061 .vb 2062 Suppose m=n=2 and block size(bs) = 2 The array is 2063 2064 1 2 | 3 4 2065 5 6 | 7 8 2066 - - - | - - - 2067 9 10 | 11 12 2068 13 14 | 15 16 2069 2070 v[] should be passed in like 2071 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2072 2073 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2074 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2075 .ve 2076 2077 Fortran Notes: 2078 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2079 .vb 2080 call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 2081 .ve 2082 2083 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2084 2085 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2086 @*/ 2087 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2088 { 2089 PetscFunctionBeginHot; 2090 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2091 PetscValidType(mat, 1); 2092 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2093 PetscAssertPointer(idxm, 3); 2094 PetscAssertPointer(idxn, 5); 2095 MatCheckPreallocated(mat, 1); 2096 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2097 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2098 if (PetscDefined(USE_DEBUG)) { 2099 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2100 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2101 } 2102 if (PetscDefined(USE_DEBUG)) { 2103 PetscInt rbs, cbs, M, N, i; 2104 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2105 PetscCall(MatGetSize(mat, &M, &N)); 2106 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than row length %" PetscInt_FMT, i, idxm[i], rbs, M); 2107 for (i = 0; i < n; i++) 2108 PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than column length %" PetscInt_FMT, i, idxn[i], cbs, N); 2109 } 2110 if (mat->assembled) { 2111 mat->was_assembled = PETSC_TRUE; 2112 mat->assembled = PETSC_FALSE; 2113 } 2114 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2115 if (mat->ops->setvaluesblocked) { 2116 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2117 } else { 2118 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2119 PetscInt i, j, bs, cbs; 2120 2121 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2122 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2123 iidxm = buf; 2124 iidxn = buf + m * bs; 2125 } else { 2126 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2127 iidxm = bufr; 2128 iidxn = bufc; 2129 } 2130 for (i = 0; i < m; i++) { 2131 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2132 } 2133 if (m != n || bs != cbs || idxm != idxn) { 2134 for (i = 0; i < n; i++) { 2135 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2136 } 2137 } else iidxn = iidxm; 2138 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2139 PetscCall(PetscFree2(bufr, bufc)); 2140 } 2141 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2142 PetscFunctionReturn(PETSC_SUCCESS); 2143 } 2144 2145 /*@ 2146 MatGetValues - Gets a block of local values from a matrix. 2147 2148 Not Collective; can only return values that are owned by the give process 2149 2150 Input Parameters: 2151 + mat - the matrix 2152 . v - a logically two-dimensional array for storing the values 2153 . m - the number of rows 2154 . idxm - the global indices of the rows 2155 . n - the number of columns 2156 - idxn - the global indices of the columns 2157 2158 Level: advanced 2159 2160 Notes: 2161 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2162 The values, `v`, are then returned in a row-oriented format, 2163 analogous to that used by default in `MatSetValues()`. 2164 2165 `MatGetValues()` uses 0-based row and column numbers in 2166 Fortran as well as in C. 2167 2168 `MatGetValues()` requires that the matrix has been assembled 2169 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2170 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2171 without intermediate matrix assembly. 2172 2173 Negative row or column indices will be ignored and those locations in `v` will be 2174 left unchanged. 2175 2176 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2177 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2178 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2179 2180 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2181 @*/ 2182 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2183 { 2184 PetscFunctionBegin; 2185 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2186 PetscValidType(mat, 1); 2187 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2188 PetscAssertPointer(idxm, 3); 2189 PetscAssertPointer(idxn, 5); 2190 PetscAssertPointer(v, 6); 2191 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2192 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2193 MatCheckPreallocated(mat, 1); 2194 2195 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2196 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2197 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2198 PetscFunctionReturn(PETSC_SUCCESS); 2199 } 2200 2201 /*@ 2202 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2203 defined previously by `MatSetLocalToGlobalMapping()` 2204 2205 Not Collective 2206 2207 Input Parameters: 2208 + mat - the matrix 2209 . nrow - number of rows 2210 . irow - the row local indices 2211 . ncol - number of columns 2212 - icol - the column local indices 2213 2214 Output Parameter: 2215 . y - a logically two-dimensional array of values 2216 2217 Level: advanced 2218 2219 Notes: 2220 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2221 2222 This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering, 2223 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2224 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2225 with `MatSetLocalToGlobalMapping()`. 2226 2227 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2228 `MatSetValuesLocal()`, `MatGetValues()` 2229 @*/ 2230 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2231 { 2232 PetscFunctionBeginHot; 2233 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2234 PetscValidType(mat, 1); 2235 MatCheckPreallocated(mat, 1); 2236 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2237 PetscAssertPointer(irow, 3); 2238 PetscAssertPointer(icol, 5); 2239 if (PetscDefined(USE_DEBUG)) { 2240 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2241 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2242 } 2243 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2244 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2245 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2246 else { 2247 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2248 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2249 irowm = buf; 2250 icolm = buf + nrow; 2251 } else { 2252 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2253 irowm = bufr; 2254 icolm = bufc; 2255 } 2256 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2257 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2258 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2259 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2260 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2261 PetscCall(PetscFree2(bufr, bufc)); 2262 } 2263 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2264 PetscFunctionReturn(PETSC_SUCCESS); 2265 } 2266 2267 /*@ 2268 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2269 the same size. Currently, this can only be called once and creates the given matrix. 2270 2271 Not Collective 2272 2273 Input Parameters: 2274 + mat - the matrix 2275 . nb - the number of blocks 2276 . bs - the number of rows (and columns) in each block 2277 . rows - a concatenation of the rows for each block 2278 - v - a concatenation of logically two-dimensional arrays of values 2279 2280 Level: advanced 2281 2282 Notes: 2283 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2284 2285 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2286 2287 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2288 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2289 @*/ 2290 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2291 { 2292 PetscFunctionBegin; 2293 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2294 PetscValidType(mat, 1); 2295 PetscAssertPointer(rows, 4); 2296 PetscAssertPointer(v, 5); 2297 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2298 2299 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2300 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2301 else { 2302 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2303 } 2304 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2305 PetscFunctionReturn(PETSC_SUCCESS); 2306 } 2307 2308 /*@ 2309 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2310 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2311 using a local (per-processor) numbering. 2312 2313 Not Collective 2314 2315 Input Parameters: 2316 + x - the matrix 2317 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2318 - cmapping - column mapping 2319 2320 Level: intermediate 2321 2322 Note: 2323 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2324 2325 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2326 @*/ 2327 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2328 { 2329 PetscFunctionBegin; 2330 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2331 PetscValidType(x, 1); 2332 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2333 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2334 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2335 else { 2336 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2337 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2338 } 2339 PetscFunctionReturn(PETSC_SUCCESS); 2340 } 2341 2342 /*@ 2343 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2344 2345 Not Collective 2346 2347 Input Parameter: 2348 . A - the matrix 2349 2350 Output Parameters: 2351 + rmapping - row mapping 2352 - cmapping - column mapping 2353 2354 Level: advanced 2355 2356 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2357 @*/ 2358 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2359 { 2360 PetscFunctionBegin; 2361 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2362 PetscValidType(A, 1); 2363 if (rmapping) { 2364 PetscAssertPointer(rmapping, 2); 2365 *rmapping = A->rmap->mapping; 2366 } 2367 if (cmapping) { 2368 PetscAssertPointer(cmapping, 3); 2369 *cmapping = A->cmap->mapping; 2370 } 2371 PetscFunctionReturn(PETSC_SUCCESS); 2372 } 2373 2374 /*@ 2375 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2376 2377 Logically Collective 2378 2379 Input Parameters: 2380 + A - the matrix 2381 . rmap - row layout 2382 - cmap - column layout 2383 2384 Level: advanced 2385 2386 Note: 2387 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2388 2389 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2390 @*/ 2391 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2392 { 2393 PetscFunctionBegin; 2394 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2395 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2396 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2397 PetscFunctionReturn(PETSC_SUCCESS); 2398 } 2399 2400 /*@ 2401 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2402 2403 Not Collective 2404 2405 Input Parameter: 2406 . A - the matrix 2407 2408 Output Parameters: 2409 + rmap - row layout 2410 - cmap - column layout 2411 2412 Level: advanced 2413 2414 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2415 @*/ 2416 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2417 { 2418 PetscFunctionBegin; 2419 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2420 PetscValidType(A, 1); 2421 if (rmap) { 2422 PetscAssertPointer(rmap, 2); 2423 *rmap = A->rmap; 2424 } 2425 if (cmap) { 2426 PetscAssertPointer(cmap, 3); 2427 *cmap = A->cmap; 2428 } 2429 PetscFunctionReturn(PETSC_SUCCESS); 2430 } 2431 2432 /*@ 2433 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2434 using a local numbering of the rows and columns. 2435 2436 Not Collective 2437 2438 Input Parameters: 2439 + mat - the matrix 2440 . nrow - number of rows 2441 . irow - the row local indices 2442 . ncol - number of columns 2443 . icol - the column local indices 2444 . y - a logically two-dimensional array of values 2445 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2446 2447 Level: intermediate 2448 2449 Notes: 2450 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2451 2452 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2453 options cannot be mixed without intervening calls to the assembly 2454 routines. 2455 2456 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2457 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2458 2459 Fortran Notes: 2460 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2461 .vb 2462 call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2463 .ve 2464 2465 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2466 2467 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2468 `MatGetValuesLocal()` 2469 @*/ 2470 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2471 { 2472 PetscFunctionBeginHot; 2473 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2474 PetscValidType(mat, 1); 2475 MatCheckPreallocated(mat, 1); 2476 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2477 PetscAssertPointer(irow, 3); 2478 PetscAssertPointer(icol, 5); 2479 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2480 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2481 if (PetscDefined(USE_DEBUG)) { 2482 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2483 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2484 } 2485 2486 if (mat->assembled) { 2487 mat->was_assembled = PETSC_TRUE; 2488 mat->assembled = PETSC_FALSE; 2489 } 2490 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2491 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2492 else { 2493 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2494 const PetscInt *irowm, *icolm; 2495 2496 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2497 bufr = buf; 2498 bufc = buf + nrow; 2499 irowm = bufr; 2500 icolm = bufc; 2501 } else { 2502 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2503 irowm = bufr; 2504 icolm = bufc; 2505 } 2506 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2507 else irowm = irow; 2508 if (mat->cmap->mapping) { 2509 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2510 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2511 } else icolm = irowm; 2512 } else icolm = icol; 2513 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2514 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2515 } 2516 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2517 PetscFunctionReturn(PETSC_SUCCESS); 2518 } 2519 2520 /*@ 2521 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2522 using a local ordering of the nodes a block at a time. 2523 2524 Not Collective 2525 2526 Input Parameters: 2527 + mat - the matrix 2528 . nrow - number of rows 2529 . irow - the row local indices 2530 . ncol - number of columns 2531 . icol - the column local indices 2532 . y - a logically two-dimensional array of values 2533 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2534 2535 Level: intermediate 2536 2537 Notes: 2538 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2539 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2540 2541 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2542 options cannot be mixed without intervening calls to the assembly 2543 routines. 2544 2545 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2546 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2547 2548 Fortran Notes: 2549 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2550 .vb 2551 call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2552 .ve 2553 2554 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2555 2556 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2557 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2558 @*/ 2559 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2560 { 2561 PetscFunctionBeginHot; 2562 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2563 PetscValidType(mat, 1); 2564 MatCheckPreallocated(mat, 1); 2565 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2566 PetscAssertPointer(irow, 3); 2567 PetscAssertPointer(icol, 5); 2568 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2569 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2570 if (PetscDefined(USE_DEBUG)) { 2571 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2572 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2573 } 2574 2575 if (mat->assembled) { 2576 mat->was_assembled = PETSC_TRUE; 2577 mat->assembled = PETSC_FALSE; 2578 } 2579 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2580 PetscInt irbs, rbs; 2581 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2582 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2583 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2584 } 2585 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2586 PetscInt icbs, cbs; 2587 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2588 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2589 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2590 } 2591 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2592 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2593 else { 2594 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2595 const PetscInt *irowm, *icolm; 2596 2597 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2598 bufr = buf; 2599 bufc = buf + nrow; 2600 irowm = bufr; 2601 icolm = bufc; 2602 } else { 2603 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2604 irowm = bufr; 2605 icolm = bufc; 2606 } 2607 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2608 else irowm = irow; 2609 if (mat->cmap->mapping) { 2610 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2611 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2612 } else icolm = irowm; 2613 } else icolm = icol; 2614 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2615 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2616 } 2617 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2618 PetscFunctionReturn(PETSC_SUCCESS); 2619 } 2620 2621 /*@ 2622 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2623 2624 Collective 2625 2626 Input Parameters: 2627 + mat - the matrix 2628 - x - the vector to be multiplied 2629 2630 Output Parameter: 2631 . y - the result 2632 2633 Level: developer 2634 2635 Note: 2636 The vectors `x` and `y` cannot be the same. I.e., one cannot 2637 call `MatMultDiagonalBlock`(A,y,y). 2638 2639 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2640 @*/ 2641 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2642 { 2643 PetscFunctionBegin; 2644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2645 PetscValidType(mat, 1); 2646 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2647 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2648 2649 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2650 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2651 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2652 MatCheckPreallocated(mat, 1); 2653 2654 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2655 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2656 PetscFunctionReturn(PETSC_SUCCESS); 2657 } 2658 2659 /*@ 2660 MatMult - Computes the matrix-vector product, $y = Ax$. 2661 2662 Neighbor-wise Collective 2663 2664 Input Parameters: 2665 + mat - the matrix 2666 - x - the vector to be multiplied 2667 2668 Output Parameter: 2669 . y - the result 2670 2671 Level: beginner 2672 2673 Note: 2674 The vectors `x` and `y` cannot be the same. I.e., one cannot 2675 call `MatMult`(A,y,y). 2676 2677 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2678 @*/ 2679 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2680 { 2681 PetscFunctionBegin; 2682 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2683 PetscValidType(mat, 1); 2684 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2685 VecCheckAssembled(x); 2686 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2687 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2688 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2689 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2690 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2691 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2692 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2693 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2694 PetscCall(VecSetErrorIfLocked(y, 3)); 2695 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2696 MatCheckPreallocated(mat, 1); 2697 2698 PetscCall(VecLockReadPush(x)); 2699 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2700 PetscUseTypeMethod(mat, mult, x, y); 2701 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2702 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2703 PetscCall(VecLockReadPop(x)); 2704 PetscFunctionReturn(PETSC_SUCCESS); 2705 } 2706 2707 /*@ 2708 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2709 2710 Neighbor-wise Collective 2711 2712 Input Parameters: 2713 + mat - the matrix 2714 - x - the vector to be multiplied 2715 2716 Output Parameter: 2717 . y - the result 2718 2719 Level: beginner 2720 2721 Notes: 2722 The vectors `x` and `y` cannot be the same. I.e., one cannot 2723 call `MatMultTranspose`(A,y,y). 2724 2725 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2726 use `MatMultHermitianTranspose()` 2727 2728 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2729 @*/ 2730 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2731 { 2732 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2733 2734 PetscFunctionBegin; 2735 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2736 PetscValidType(mat, 1); 2737 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2738 VecCheckAssembled(x); 2739 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2740 2741 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2742 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2743 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2744 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2745 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2746 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2747 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2748 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2749 MatCheckPreallocated(mat, 1); 2750 2751 if (!mat->ops->multtranspose) { 2752 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2753 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2754 } else op = mat->ops->multtranspose; 2755 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2756 PetscCall(VecLockReadPush(x)); 2757 PetscCall((*op)(mat, x, y)); 2758 PetscCall(VecLockReadPop(x)); 2759 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2760 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2761 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2762 PetscFunctionReturn(PETSC_SUCCESS); 2763 } 2764 2765 /*@ 2766 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2767 2768 Neighbor-wise Collective 2769 2770 Input Parameters: 2771 + mat - the matrix 2772 - x - the vector to be multiplied 2773 2774 Output Parameter: 2775 . y - the result 2776 2777 Level: beginner 2778 2779 Notes: 2780 The vectors `x` and `y` cannot be the same. I.e., one cannot 2781 call `MatMultHermitianTranspose`(A,y,y). 2782 2783 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2784 2785 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2786 2787 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2788 @*/ 2789 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2790 { 2791 PetscFunctionBegin; 2792 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2793 PetscValidType(mat, 1); 2794 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2795 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2796 2797 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2798 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2799 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2800 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2801 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2802 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2803 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2804 MatCheckPreallocated(mat, 1); 2805 2806 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2807 #if defined(PETSC_USE_COMPLEX) 2808 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2809 PetscCall(VecLockReadPush(x)); 2810 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2811 else PetscUseTypeMethod(mat, mult, x, y); 2812 PetscCall(VecLockReadPop(x)); 2813 } else { 2814 Vec w; 2815 PetscCall(VecDuplicate(x, &w)); 2816 PetscCall(VecCopy(x, w)); 2817 PetscCall(VecConjugate(w)); 2818 PetscCall(MatMultTranspose(mat, w, y)); 2819 PetscCall(VecDestroy(&w)); 2820 PetscCall(VecConjugate(y)); 2821 } 2822 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2823 #else 2824 PetscCall(MatMultTranspose(mat, x, y)); 2825 #endif 2826 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2827 PetscFunctionReturn(PETSC_SUCCESS); 2828 } 2829 2830 /*@ 2831 MatMultAdd - Computes $v3 = v2 + A * v1$. 2832 2833 Neighbor-wise Collective 2834 2835 Input Parameters: 2836 + mat - the matrix 2837 . v1 - the vector to be multiplied by `mat` 2838 - v2 - the vector to be added to the result 2839 2840 Output Parameter: 2841 . v3 - the result 2842 2843 Level: beginner 2844 2845 Note: 2846 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2847 call `MatMultAdd`(A,v1,v2,v1). 2848 2849 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2850 @*/ 2851 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2852 { 2853 PetscFunctionBegin; 2854 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2855 PetscValidType(mat, 1); 2856 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2857 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2858 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2859 2860 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2861 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2862 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2863 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2864 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2865 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2866 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2867 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2868 MatCheckPreallocated(mat, 1); 2869 2870 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2871 PetscCall(VecLockReadPush(v1)); 2872 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2873 PetscCall(VecLockReadPop(v1)); 2874 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2875 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2876 PetscFunctionReturn(PETSC_SUCCESS); 2877 } 2878 2879 /*@ 2880 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2881 2882 Neighbor-wise Collective 2883 2884 Input Parameters: 2885 + mat - the matrix 2886 . v1 - the vector to be multiplied by the transpose of the matrix 2887 - v2 - the vector to be added to the result 2888 2889 Output Parameter: 2890 . v3 - the result 2891 2892 Level: beginner 2893 2894 Note: 2895 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2896 call `MatMultTransposeAdd`(A,v1,v2,v1). 2897 2898 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2899 @*/ 2900 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2901 { 2902 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2903 2904 PetscFunctionBegin; 2905 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2906 PetscValidType(mat, 1); 2907 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2908 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2909 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2910 2911 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2912 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2913 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2914 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2915 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2916 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2917 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2918 MatCheckPreallocated(mat, 1); 2919 2920 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2921 PetscCall(VecLockReadPush(v1)); 2922 PetscCall((*op)(mat, v1, v2, v3)); 2923 PetscCall(VecLockReadPop(v1)); 2924 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2925 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2926 PetscFunctionReturn(PETSC_SUCCESS); 2927 } 2928 2929 /*@ 2930 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2931 2932 Neighbor-wise Collective 2933 2934 Input Parameters: 2935 + mat - the matrix 2936 . v1 - the vector to be multiplied by the Hermitian transpose 2937 - v2 - the vector to be added to the result 2938 2939 Output Parameter: 2940 . v3 - the result 2941 2942 Level: beginner 2943 2944 Note: 2945 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2946 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2947 2948 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2949 @*/ 2950 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2951 { 2952 PetscFunctionBegin; 2953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2954 PetscValidType(mat, 1); 2955 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2956 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2957 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2958 2959 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2960 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2961 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2962 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2963 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2964 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2965 MatCheckPreallocated(mat, 1); 2966 2967 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2968 PetscCall(VecLockReadPush(v1)); 2969 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2970 else { 2971 Vec w, z; 2972 PetscCall(VecDuplicate(v1, &w)); 2973 PetscCall(VecCopy(v1, w)); 2974 PetscCall(VecConjugate(w)); 2975 PetscCall(VecDuplicate(v3, &z)); 2976 PetscCall(MatMultTranspose(mat, w, z)); 2977 PetscCall(VecDestroy(&w)); 2978 PetscCall(VecConjugate(z)); 2979 if (v2 != v3) { 2980 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2981 } else { 2982 PetscCall(VecAXPY(v3, 1.0, z)); 2983 } 2984 PetscCall(VecDestroy(&z)); 2985 } 2986 PetscCall(VecLockReadPop(v1)); 2987 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2988 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2989 PetscFunctionReturn(PETSC_SUCCESS); 2990 } 2991 2992 /*@ 2993 MatGetFactorType - gets the type of factorization a matrix is 2994 2995 Not Collective 2996 2997 Input Parameter: 2998 . mat - the matrix 2999 3000 Output Parameter: 3001 . 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` 3002 3003 Level: intermediate 3004 3005 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3006 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3007 @*/ 3008 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3009 { 3010 PetscFunctionBegin; 3011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3012 PetscValidType(mat, 1); 3013 PetscAssertPointer(t, 2); 3014 *t = mat->factortype; 3015 PetscFunctionReturn(PETSC_SUCCESS); 3016 } 3017 3018 /*@ 3019 MatSetFactorType - sets the type of factorization a matrix is 3020 3021 Logically Collective 3022 3023 Input Parameters: 3024 + mat - the matrix 3025 - 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` 3026 3027 Level: intermediate 3028 3029 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3030 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3031 @*/ 3032 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3033 { 3034 PetscFunctionBegin; 3035 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3036 PetscValidType(mat, 1); 3037 mat->factortype = t; 3038 PetscFunctionReturn(PETSC_SUCCESS); 3039 } 3040 3041 /*@ 3042 MatGetInfo - Returns information about matrix storage (number of 3043 nonzeros, memory, etc.). 3044 3045 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3046 3047 Input Parameters: 3048 + mat - the matrix 3049 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 3050 3051 Output Parameter: 3052 . info - matrix information context 3053 3054 Options Database Key: 3055 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3056 3057 Level: intermediate 3058 3059 Notes: 3060 The `MatInfo` context contains a variety of matrix data, including 3061 number of nonzeros allocated and used, number of mallocs during 3062 matrix assembly, etc. Additional information for factored matrices 3063 is provided (such as the fill ratio, number of mallocs during 3064 factorization, etc.). 3065 3066 Example: 3067 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3068 data within the `MatInfo` context. For example, 3069 .vb 3070 MatInfo info; 3071 Mat A; 3072 double mal, nz_a, nz_u; 3073 3074 MatGetInfo(A, MAT_LOCAL, &info); 3075 mal = info.mallocs; 3076 nz_a = info.nz_allocated; 3077 .ve 3078 3079 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3080 @*/ 3081 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3082 { 3083 PetscFunctionBegin; 3084 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3085 PetscValidType(mat, 1); 3086 PetscAssertPointer(info, 3); 3087 MatCheckPreallocated(mat, 1); 3088 PetscUseTypeMethod(mat, getinfo, flag, info); 3089 PetscFunctionReturn(PETSC_SUCCESS); 3090 } 3091 3092 /* 3093 This is used by external packages where it is not easy to get the info from the actual 3094 matrix factorization. 3095 */ 3096 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3097 { 3098 PetscFunctionBegin; 3099 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3100 PetscFunctionReturn(PETSC_SUCCESS); 3101 } 3102 3103 /*@ 3104 MatLUFactor - Performs in-place LU factorization of matrix. 3105 3106 Collective 3107 3108 Input Parameters: 3109 + mat - the matrix 3110 . row - row permutation 3111 . col - column permutation 3112 - info - options for factorization, includes 3113 .vb 3114 fill - expected fill as ratio of original fill. 3115 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3116 Run with the option -info to determine an optimal value to use 3117 .ve 3118 3119 Level: developer 3120 3121 Notes: 3122 Most users should employ the `KSP` interface for linear solvers 3123 instead of working directly with matrix algebra routines such as this. 3124 See, e.g., `KSPCreate()`. 3125 3126 This changes the state of the matrix to a factored matrix; it cannot be used 3127 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3128 3129 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3130 when not using `KSP`. 3131 3132 Fortran Note: 3133 A valid (non-null) `info` argument must be provided 3134 3135 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3136 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3137 @*/ 3138 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3139 { 3140 MatFactorInfo tinfo; 3141 3142 PetscFunctionBegin; 3143 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3144 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3145 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3146 if (info) PetscAssertPointer(info, 4); 3147 PetscValidType(mat, 1); 3148 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3149 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3150 MatCheckPreallocated(mat, 1); 3151 if (!info) { 3152 PetscCall(MatFactorInfoInitialize(&tinfo)); 3153 info = &tinfo; 3154 } 3155 3156 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3157 PetscUseTypeMethod(mat, lufactor, row, col, info); 3158 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3159 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3160 PetscFunctionReturn(PETSC_SUCCESS); 3161 } 3162 3163 /*@ 3164 MatILUFactor - Performs in-place ILU factorization of matrix. 3165 3166 Collective 3167 3168 Input Parameters: 3169 + mat - the matrix 3170 . row - row permutation 3171 . col - column permutation 3172 - info - structure containing 3173 .vb 3174 levels - number of levels of fill. 3175 expected fill - as ratio of original fill. 3176 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3177 missing diagonal entries) 3178 .ve 3179 3180 Level: developer 3181 3182 Notes: 3183 Most users should employ the `KSP` interface for linear solvers 3184 instead of working directly with matrix algebra routines such as this. 3185 See, e.g., `KSPCreate()`. 3186 3187 Probably really in-place only when level of fill is zero, otherwise allocates 3188 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3189 when not using `KSP`. 3190 3191 Fortran Note: 3192 A valid (non-null) `info` argument must be provided 3193 3194 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3195 @*/ 3196 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3197 { 3198 PetscFunctionBegin; 3199 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3200 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3201 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3202 PetscAssertPointer(info, 4); 3203 PetscValidType(mat, 1); 3204 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3205 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3206 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3207 MatCheckPreallocated(mat, 1); 3208 3209 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3210 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3211 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3212 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3213 PetscFunctionReturn(PETSC_SUCCESS); 3214 } 3215 3216 /*@ 3217 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3218 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3219 3220 Collective 3221 3222 Input Parameters: 3223 + fact - the factor matrix obtained with `MatGetFactor()` 3224 . mat - the matrix 3225 . row - the row permutation 3226 . col - the column permutation 3227 - info - options for factorization, includes 3228 .vb 3229 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3230 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3231 .ve 3232 3233 Level: developer 3234 3235 Notes: 3236 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3237 3238 Most users should employ the simplified `KSP` interface for linear solvers 3239 instead of working directly with matrix algebra routines such as this. 3240 See, e.g., `KSPCreate()`. 3241 3242 Fortran Note: 3243 A valid (non-null) `info` argument must be provided 3244 3245 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3246 @*/ 3247 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3248 { 3249 MatFactorInfo tinfo; 3250 3251 PetscFunctionBegin; 3252 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3253 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3254 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3255 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3256 if (info) PetscAssertPointer(info, 5); 3257 PetscValidType(fact, 1); 3258 PetscValidType(mat, 2); 3259 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3260 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3261 MatCheckPreallocated(mat, 2); 3262 if (!info) { 3263 PetscCall(MatFactorInfoInitialize(&tinfo)); 3264 info = &tinfo; 3265 } 3266 3267 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3268 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3269 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3270 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3271 PetscFunctionReturn(PETSC_SUCCESS); 3272 } 3273 3274 /*@ 3275 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3276 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3277 3278 Collective 3279 3280 Input Parameters: 3281 + fact - the factor matrix obtained with `MatGetFactor()` 3282 . mat - the matrix 3283 - info - options for factorization 3284 3285 Level: developer 3286 3287 Notes: 3288 See `MatLUFactor()` for in-place factorization. See 3289 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3290 3291 Most users should employ the `KSP` interface for linear solvers 3292 instead of working directly with matrix algebra routines such as this. 3293 See, e.g., `KSPCreate()`. 3294 3295 Fortran Note: 3296 A valid (non-null) `info` argument must be provided 3297 3298 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3299 @*/ 3300 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3301 { 3302 MatFactorInfo tinfo; 3303 3304 PetscFunctionBegin; 3305 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3306 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3307 PetscValidType(fact, 1); 3308 PetscValidType(mat, 2); 3309 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3310 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3311 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3312 3313 MatCheckPreallocated(mat, 2); 3314 if (!info) { 3315 PetscCall(MatFactorInfoInitialize(&tinfo)); 3316 info = &tinfo; 3317 } 3318 3319 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3320 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3321 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3322 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3323 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3324 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3325 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3326 PetscFunctionReturn(PETSC_SUCCESS); 3327 } 3328 3329 /*@ 3330 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3331 symmetric matrix. 3332 3333 Collective 3334 3335 Input Parameters: 3336 + mat - the matrix 3337 . perm - row and column permutations 3338 - info - expected fill as ratio of original fill 3339 3340 Level: developer 3341 3342 Notes: 3343 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3344 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3345 3346 Most users should employ the `KSP` interface for linear solvers 3347 instead of working directly with matrix algebra routines such as this. 3348 See, e.g., `KSPCreate()`. 3349 3350 Fortran Note: 3351 A valid (non-null) `info` argument must be provided 3352 3353 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3354 `MatGetOrdering()` 3355 @*/ 3356 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3357 { 3358 MatFactorInfo tinfo; 3359 3360 PetscFunctionBegin; 3361 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3362 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3363 if (info) PetscAssertPointer(info, 3); 3364 PetscValidType(mat, 1); 3365 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3366 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3367 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3368 MatCheckPreallocated(mat, 1); 3369 if (!info) { 3370 PetscCall(MatFactorInfoInitialize(&tinfo)); 3371 info = &tinfo; 3372 } 3373 3374 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3375 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3376 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3377 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3378 PetscFunctionReturn(PETSC_SUCCESS); 3379 } 3380 3381 /*@ 3382 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3383 of a symmetric matrix. 3384 3385 Collective 3386 3387 Input Parameters: 3388 + fact - the factor matrix obtained with `MatGetFactor()` 3389 . mat - the matrix 3390 . perm - row and column permutations 3391 - info - options for factorization, includes 3392 .vb 3393 fill - expected fill as ratio of original fill. 3394 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3395 Run with the option -info to determine an optimal value to use 3396 .ve 3397 3398 Level: developer 3399 3400 Notes: 3401 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3402 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3403 3404 Most users should employ the `KSP` interface for linear solvers 3405 instead of working directly with matrix algebra routines such as this. 3406 See, e.g., `KSPCreate()`. 3407 3408 Fortran Note: 3409 A valid (non-null) `info` argument must be provided 3410 3411 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3412 `MatGetOrdering()` 3413 @*/ 3414 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3415 { 3416 MatFactorInfo tinfo; 3417 3418 PetscFunctionBegin; 3419 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3420 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3421 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3422 if (info) PetscAssertPointer(info, 4); 3423 PetscValidType(fact, 1); 3424 PetscValidType(mat, 2); 3425 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3426 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3427 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3428 MatCheckPreallocated(mat, 2); 3429 if (!info) { 3430 PetscCall(MatFactorInfoInitialize(&tinfo)); 3431 info = &tinfo; 3432 } 3433 3434 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3435 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3436 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3437 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3438 PetscFunctionReturn(PETSC_SUCCESS); 3439 } 3440 3441 /*@ 3442 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3443 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3444 `MatCholeskyFactorSymbolic()`. 3445 3446 Collective 3447 3448 Input Parameters: 3449 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3450 . mat - the initial matrix that is to be factored 3451 - info - options for factorization 3452 3453 Level: developer 3454 3455 Note: 3456 Most users should employ the `KSP` interface for linear solvers 3457 instead of working directly with matrix algebra routines such as this. 3458 See, e.g., `KSPCreate()`. 3459 3460 Fortran Note: 3461 A valid (non-null) `info` argument must be provided 3462 3463 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3464 @*/ 3465 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3466 { 3467 MatFactorInfo tinfo; 3468 3469 PetscFunctionBegin; 3470 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3471 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3472 PetscValidType(fact, 1); 3473 PetscValidType(mat, 2); 3474 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3475 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3476 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3477 MatCheckPreallocated(mat, 2); 3478 if (!info) { 3479 PetscCall(MatFactorInfoInitialize(&tinfo)); 3480 info = &tinfo; 3481 } 3482 3483 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3484 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3485 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3486 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3487 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3488 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3489 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3490 PetscFunctionReturn(PETSC_SUCCESS); 3491 } 3492 3493 /*@ 3494 MatQRFactor - Performs in-place QR factorization of matrix. 3495 3496 Collective 3497 3498 Input Parameters: 3499 + mat - the matrix 3500 . col - column permutation 3501 - info - options for factorization, includes 3502 .vb 3503 fill - expected fill as ratio of original fill. 3504 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3505 Run with the option -info to determine an optimal value to use 3506 .ve 3507 3508 Level: developer 3509 3510 Notes: 3511 Most users should employ the `KSP` interface for linear solvers 3512 instead of working directly with matrix algebra routines such as this. 3513 See, e.g., `KSPCreate()`. 3514 3515 This changes the state of the matrix to a factored matrix; it cannot be used 3516 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3517 3518 Fortran Note: 3519 A valid (non-null) `info` argument must be provided 3520 3521 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3522 `MatSetUnfactored()` 3523 @*/ 3524 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3525 { 3526 PetscFunctionBegin; 3527 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3528 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3529 if (info) PetscAssertPointer(info, 3); 3530 PetscValidType(mat, 1); 3531 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3532 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3533 MatCheckPreallocated(mat, 1); 3534 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3535 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3536 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3537 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3538 PetscFunctionReturn(PETSC_SUCCESS); 3539 } 3540 3541 /*@ 3542 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3543 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3544 3545 Collective 3546 3547 Input Parameters: 3548 + fact - the factor matrix obtained with `MatGetFactor()` 3549 . mat - the matrix 3550 . col - column permutation 3551 - info - options for factorization, includes 3552 .vb 3553 fill - expected fill as ratio of original fill. 3554 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3555 Run with the option -info to determine an optimal value to use 3556 .ve 3557 3558 Level: developer 3559 3560 Note: 3561 Most users should employ the `KSP` interface for linear solvers 3562 instead of working directly with matrix algebra routines such as this. 3563 See, e.g., `KSPCreate()`. 3564 3565 Fortran Note: 3566 A valid (non-null) `info` argument must be provided 3567 3568 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3569 @*/ 3570 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3571 { 3572 MatFactorInfo tinfo; 3573 3574 PetscFunctionBegin; 3575 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3576 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3577 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3578 if (info) PetscAssertPointer(info, 4); 3579 PetscValidType(fact, 1); 3580 PetscValidType(mat, 2); 3581 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3582 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3583 MatCheckPreallocated(mat, 2); 3584 if (!info) { 3585 PetscCall(MatFactorInfoInitialize(&tinfo)); 3586 info = &tinfo; 3587 } 3588 3589 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3590 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3591 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3592 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3593 PetscFunctionReturn(PETSC_SUCCESS); 3594 } 3595 3596 /*@ 3597 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3598 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3599 3600 Collective 3601 3602 Input Parameters: 3603 + fact - the factor matrix obtained with `MatGetFactor()` 3604 . mat - the matrix 3605 - info - options for factorization 3606 3607 Level: developer 3608 3609 Notes: 3610 See `MatQRFactor()` for in-place factorization. 3611 3612 Most users should employ the `KSP` interface for linear solvers 3613 instead of working directly with matrix algebra routines such as this. 3614 See, e.g., `KSPCreate()`. 3615 3616 Fortran Note: 3617 A valid (non-null) `info` argument must be provided 3618 3619 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3620 @*/ 3621 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3622 { 3623 MatFactorInfo tinfo; 3624 3625 PetscFunctionBegin; 3626 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3627 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3628 PetscValidType(fact, 1); 3629 PetscValidType(mat, 2); 3630 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3631 PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3632 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3633 3634 MatCheckPreallocated(mat, 2); 3635 if (!info) { 3636 PetscCall(MatFactorInfoInitialize(&tinfo)); 3637 info = &tinfo; 3638 } 3639 3640 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3641 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3642 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3643 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3644 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3645 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3646 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3647 PetscFunctionReturn(PETSC_SUCCESS); 3648 } 3649 3650 /*@ 3651 MatSolve - Solves $A x = b$, given a factored matrix. 3652 3653 Neighbor-wise Collective 3654 3655 Input Parameters: 3656 + mat - the factored matrix 3657 - b - the right-hand-side vector 3658 3659 Output Parameter: 3660 . x - the result vector 3661 3662 Level: developer 3663 3664 Notes: 3665 The vectors `b` and `x` cannot be the same. I.e., one cannot 3666 call `MatSolve`(A,x,x). 3667 3668 Most users should employ the `KSP` interface for linear solvers 3669 instead of working directly with matrix algebra routines such as this. 3670 See, e.g., `KSPCreate()`. 3671 3672 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3673 @*/ 3674 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3675 { 3676 PetscFunctionBegin; 3677 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3678 PetscValidType(mat, 1); 3679 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3680 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3681 PetscCheckSameComm(mat, 1, b, 2); 3682 PetscCheckSameComm(mat, 1, x, 3); 3683 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3684 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3685 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3686 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3687 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3688 MatCheckPreallocated(mat, 1); 3689 3690 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3691 PetscCall(VecFlag(x, mat->factorerrortype)); 3692 if (mat->factorerrortype) { 3693 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3694 } else PetscUseTypeMethod(mat, solve, b, x); 3695 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3696 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3697 PetscFunctionReturn(PETSC_SUCCESS); 3698 } 3699 3700 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3701 { 3702 Vec b, x; 3703 PetscInt N, i; 3704 PetscErrorCode (*f)(Mat, Vec, Vec); 3705 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3706 3707 PetscFunctionBegin; 3708 if (A->factorerrortype) { 3709 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3710 PetscCall(MatSetInf(X)); 3711 PetscFunctionReturn(PETSC_SUCCESS); 3712 } 3713 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3714 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3715 PetscCall(MatBoundToCPU(A, &Abound)); 3716 if (!Abound) { 3717 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3718 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3719 } 3720 #if PetscDefined(HAVE_CUDA) 3721 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3722 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3723 #elif PetscDefined(HAVE_HIP) 3724 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3725 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3726 #endif 3727 PetscCall(MatGetSize(B, NULL, &N)); 3728 for (i = 0; i < N; i++) { 3729 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3730 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3731 PetscCall((*f)(A, b, x)); 3732 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3733 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3734 } 3735 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3736 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3737 PetscFunctionReturn(PETSC_SUCCESS); 3738 } 3739 3740 /*@ 3741 MatMatSolve - Solves $A X = B$, given a factored matrix. 3742 3743 Neighbor-wise Collective 3744 3745 Input Parameters: 3746 + A - the factored matrix 3747 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3748 3749 Output Parameter: 3750 . X - the result matrix (dense matrix) 3751 3752 Level: developer 3753 3754 Note: 3755 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3756 otherwise, `B` and `X` cannot be the same. 3757 3758 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3759 @*/ 3760 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3761 { 3762 PetscFunctionBegin; 3763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3764 PetscValidType(A, 1); 3765 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3766 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3767 PetscCheckSameComm(A, 1, B, 2); 3768 PetscCheckSameComm(A, 1, X, 3); 3769 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3770 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3771 PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3772 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3773 MatCheckPreallocated(A, 1); 3774 3775 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3776 if (!A->ops->matsolve) { 3777 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3778 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3779 } else PetscUseTypeMethod(A, matsolve, B, X); 3780 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3781 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3782 PetscFunctionReturn(PETSC_SUCCESS); 3783 } 3784 3785 /*@ 3786 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3787 3788 Neighbor-wise Collective 3789 3790 Input Parameters: 3791 + A - the factored matrix 3792 - B - the right-hand-side matrix (`MATDENSE` matrix) 3793 3794 Output Parameter: 3795 . X - the result matrix (dense matrix) 3796 3797 Level: developer 3798 3799 Note: 3800 The matrices `B` and `X` cannot be the same. I.e., one cannot 3801 call `MatMatSolveTranspose`(A,X,X). 3802 3803 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3804 @*/ 3805 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3806 { 3807 PetscFunctionBegin; 3808 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3809 PetscValidType(A, 1); 3810 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3811 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3812 PetscCheckSameComm(A, 1, B, 2); 3813 PetscCheckSameComm(A, 1, X, 3); 3814 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3815 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3816 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3817 PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n); 3818 PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3819 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3820 MatCheckPreallocated(A, 1); 3821 3822 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3823 if (!A->ops->matsolvetranspose) { 3824 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3825 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3826 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3827 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3828 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3829 PetscFunctionReturn(PETSC_SUCCESS); 3830 } 3831 3832 /*@ 3833 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3834 3835 Neighbor-wise Collective 3836 3837 Input Parameters: 3838 + A - the factored matrix 3839 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3840 3841 Output Parameter: 3842 . X - the result matrix (dense matrix) 3843 3844 Level: developer 3845 3846 Note: 3847 For MUMPS, it only supports centralized sparse compressed column format on the host processor for right-hand side matrix. User must create `Bt` in sparse compressed row 3848 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3849 3850 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3851 @*/ 3852 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3853 { 3854 PetscFunctionBegin; 3855 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3856 PetscValidType(A, 1); 3857 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3858 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3859 PetscCheckSameComm(A, 1, Bt, 2); 3860 PetscCheckSameComm(A, 1, X, 3); 3861 3862 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3863 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3864 PetscCheck(A->rmap->N == Bt->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, Bt->cmap->N); 3865 PetscCheck(X->cmap->N >= Bt->rmap->N, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as row number of the rhs matrix"); 3866 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3867 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3868 MatCheckPreallocated(A, 1); 3869 3870 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3871 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3872 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3873 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3874 PetscFunctionReturn(PETSC_SUCCESS); 3875 } 3876 3877 /*@ 3878 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3879 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3880 3881 Neighbor-wise Collective 3882 3883 Input Parameters: 3884 + mat - the factored matrix 3885 - b - the right-hand-side vector 3886 3887 Output Parameter: 3888 . x - the result vector 3889 3890 Level: developer 3891 3892 Notes: 3893 `MatSolve()` should be used for most applications, as it performs 3894 a forward solve followed by a backward solve. 3895 3896 The vectors `b` and `x` cannot be the same, i.e., one cannot 3897 call `MatForwardSolve`(A,x,x). 3898 3899 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3900 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3901 `MatForwardSolve()` solves $U^T*D y = b$, and 3902 `MatBackwardSolve()` solves $U x = y$. 3903 Thus they do not provide a symmetric preconditioner. 3904 3905 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3906 @*/ 3907 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3908 { 3909 PetscFunctionBegin; 3910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3911 PetscValidType(mat, 1); 3912 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3913 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3914 PetscCheckSameComm(mat, 1, b, 2); 3915 PetscCheckSameComm(mat, 1, x, 3); 3916 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3917 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3918 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3919 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3920 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3921 MatCheckPreallocated(mat, 1); 3922 3923 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3924 PetscUseTypeMethod(mat, forwardsolve, b, x); 3925 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3926 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3927 PetscFunctionReturn(PETSC_SUCCESS); 3928 } 3929 3930 /*@ 3931 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3932 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3933 3934 Neighbor-wise Collective 3935 3936 Input Parameters: 3937 + mat - the factored matrix 3938 - b - the right-hand-side vector 3939 3940 Output Parameter: 3941 . x - the result vector 3942 3943 Level: developer 3944 3945 Notes: 3946 `MatSolve()` should be used for most applications, as it performs 3947 a forward solve followed by a backward solve. 3948 3949 The vectors `b` and `x` cannot be the same. I.e., one cannot 3950 call `MatBackwardSolve`(A,x,x). 3951 3952 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3953 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3954 `MatForwardSolve()` solves $U^T*D y = b$, and 3955 `MatBackwardSolve()` solves $U x = y$. 3956 Thus they do not provide a symmetric preconditioner. 3957 3958 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3959 @*/ 3960 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3961 { 3962 PetscFunctionBegin; 3963 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3964 PetscValidType(mat, 1); 3965 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3966 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3967 PetscCheckSameComm(mat, 1, b, 2); 3968 PetscCheckSameComm(mat, 1, x, 3); 3969 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3970 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3971 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3972 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3973 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3974 MatCheckPreallocated(mat, 1); 3975 3976 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3977 PetscUseTypeMethod(mat, backwardsolve, b, x); 3978 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3979 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3980 PetscFunctionReturn(PETSC_SUCCESS); 3981 } 3982 3983 /*@ 3984 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3985 3986 Neighbor-wise Collective 3987 3988 Input Parameters: 3989 + mat - the factored matrix 3990 . b - the right-hand-side vector 3991 - y - the vector to be added to 3992 3993 Output Parameter: 3994 . x - the result vector 3995 3996 Level: developer 3997 3998 Note: 3999 The vectors `b` and `x` cannot be the same. I.e., one cannot 4000 call `MatSolveAdd`(A,x,y,x). 4001 4002 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4003 @*/ 4004 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4005 { 4006 PetscScalar one = 1.0; 4007 Vec tmp; 4008 4009 PetscFunctionBegin; 4010 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4011 PetscValidType(mat, 1); 4012 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4013 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4014 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4015 PetscCheckSameComm(mat, 1, b, 2); 4016 PetscCheckSameComm(mat, 1, y, 3); 4017 PetscCheckSameComm(mat, 1, x, 4); 4018 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4019 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 4020 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 4021 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 4022 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 4023 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 4024 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4025 MatCheckPreallocated(mat, 1); 4026 4027 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4028 PetscCall(VecFlag(x, mat->factorerrortype)); 4029 if (mat->factorerrortype) { 4030 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4031 } else if (mat->ops->solveadd) { 4032 PetscUseTypeMethod(mat, solveadd, b, y, x); 4033 } else { 4034 /* do the solve then the add manually */ 4035 if (x != y) { 4036 PetscCall(MatSolve(mat, b, x)); 4037 PetscCall(VecAXPY(x, one, y)); 4038 } else { 4039 PetscCall(VecDuplicate(x, &tmp)); 4040 PetscCall(VecCopy(x, tmp)); 4041 PetscCall(MatSolve(mat, b, x)); 4042 PetscCall(VecAXPY(x, one, tmp)); 4043 PetscCall(VecDestroy(&tmp)); 4044 } 4045 } 4046 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4047 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4048 PetscFunctionReturn(PETSC_SUCCESS); 4049 } 4050 4051 /*@ 4052 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4053 4054 Neighbor-wise Collective 4055 4056 Input Parameters: 4057 + mat - the factored matrix 4058 - b - the right-hand-side vector 4059 4060 Output Parameter: 4061 . x - the result vector 4062 4063 Level: developer 4064 4065 Notes: 4066 The vectors `b` and `x` cannot be the same. I.e., one cannot 4067 call `MatSolveTranspose`(A,x,x). 4068 4069 Most users should employ the `KSP` interface for linear solvers 4070 instead of working directly with matrix algebra routines such as this. 4071 See, e.g., `KSPCreate()`. 4072 4073 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4074 @*/ 4075 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4076 { 4077 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4078 4079 PetscFunctionBegin; 4080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4081 PetscValidType(mat, 1); 4082 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4083 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4084 PetscCheckSameComm(mat, 1, b, 2); 4085 PetscCheckSameComm(mat, 1, x, 3); 4086 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4087 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 4088 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 4089 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4090 MatCheckPreallocated(mat, 1); 4091 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4092 PetscCall(VecFlag(x, mat->factorerrortype)); 4093 if (mat->factorerrortype) { 4094 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4095 } else { 4096 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4097 PetscCall((*f)(mat, b, x)); 4098 } 4099 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4100 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4101 PetscFunctionReturn(PETSC_SUCCESS); 4102 } 4103 4104 /*@ 4105 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4106 factored matrix. 4107 4108 Neighbor-wise Collective 4109 4110 Input Parameters: 4111 + mat - the factored matrix 4112 . b - the right-hand-side vector 4113 - y - the vector to be added to 4114 4115 Output Parameter: 4116 . x - the result vector 4117 4118 Level: developer 4119 4120 Note: 4121 The vectors `b` and `x` cannot be the same. I.e., one cannot 4122 call `MatSolveTransposeAdd`(A,x,y,x). 4123 4124 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4125 @*/ 4126 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4127 { 4128 PetscScalar one = 1.0; 4129 Vec tmp; 4130 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4131 4132 PetscFunctionBegin; 4133 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4134 PetscValidType(mat, 1); 4135 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4136 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4137 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4138 PetscCheckSameComm(mat, 1, b, 2); 4139 PetscCheckSameComm(mat, 1, y, 3); 4140 PetscCheckSameComm(mat, 1, x, 4); 4141 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4142 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 4143 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 4144 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 4145 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 4146 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4147 MatCheckPreallocated(mat, 1); 4148 4149 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4150 PetscCall(VecFlag(x, mat->factorerrortype)); 4151 if (mat->factorerrortype) { 4152 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4153 } else if (f) { 4154 PetscCall((*f)(mat, b, y, x)); 4155 } else { 4156 /* do the solve then the add manually */ 4157 if (x != y) { 4158 PetscCall(MatSolveTranspose(mat, b, x)); 4159 PetscCall(VecAXPY(x, one, y)); 4160 } else { 4161 PetscCall(VecDuplicate(x, &tmp)); 4162 PetscCall(VecCopy(x, tmp)); 4163 PetscCall(MatSolveTranspose(mat, b, x)); 4164 PetscCall(VecAXPY(x, one, tmp)); 4165 PetscCall(VecDestroy(&tmp)); 4166 } 4167 } 4168 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4169 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4170 PetscFunctionReturn(PETSC_SUCCESS); 4171 } 4172 4173 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4174 /*@ 4175 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4176 4177 Neighbor-wise Collective 4178 4179 Input Parameters: 4180 + mat - the matrix 4181 . b - the right-hand side 4182 . omega - the relaxation factor 4183 . flag - flag indicating the type of SOR (see below) 4184 . shift - diagonal shift 4185 . its - the number of iterations 4186 - lits - the number of local iterations 4187 4188 Output Parameter: 4189 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4190 4191 SOR Flags: 4192 + `SOR_FORWARD_SWEEP` - forward SOR 4193 . `SOR_BACKWARD_SWEEP` - backward SOR 4194 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4195 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4196 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4197 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4198 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4199 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4200 upper/lower triangular part of matrix to 4201 vector (with omega) 4202 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4203 4204 Level: developer 4205 4206 Notes: 4207 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4208 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4209 on each processor. 4210 4211 Application programmers will not generally use `MatSOR()` directly, 4212 but instead will employ the `KSP`/`PC` interface. 4213 4214 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4215 4216 Most users should employ the `KSP` interface for linear solvers 4217 instead of working directly with matrix algebra routines such as this. 4218 See, e.g., `KSPCreate()`. 4219 4220 Vectors `x` and `b` CANNOT be the same 4221 4222 The flags are implemented as bitwise inclusive or operations. 4223 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4224 to specify a zero initial guess for SSOR. 4225 4226 Developer Note: 4227 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4228 4229 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4230 @*/ 4231 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4232 { 4233 PetscFunctionBegin; 4234 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4235 PetscValidType(mat, 1); 4236 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4237 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4238 PetscCheckSameComm(mat, 1, b, 2); 4239 PetscCheckSameComm(mat, 1, x, 8); 4240 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4241 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4242 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 4243 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 4244 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 4245 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4246 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4247 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4248 4249 MatCheckPreallocated(mat, 1); 4250 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4251 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4252 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4253 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4254 PetscFunctionReturn(PETSC_SUCCESS); 4255 } 4256 4257 /* 4258 Default matrix copy routine. 4259 */ 4260 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4261 { 4262 PetscInt i, rstart = 0, rend = 0, nz; 4263 const PetscInt *cwork; 4264 const PetscScalar *vwork; 4265 4266 PetscFunctionBegin; 4267 if (B->assembled) PetscCall(MatZeroEntries(B)); 4268 if (str == SAME_NONZERO_PATTERN) { 4269 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4270 for (i = rstart; i < rend; i++) { 4271 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4272 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4273 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4274 } 4275 } else { 4276 PetscCall(MatAYPX(B, 0.0, A, str)); 4277 } 4278 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4279 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4280 PetscFunctionReturn(PETSC_SUCCESS); 4281 } 4282 4283 /*@ 4284 MatCopy - Copies a matrix to another matrix. 4285 4286 Collective 4287 4288 Input Parameters: 4289 + A - the matrix 4290 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4291 4292 Output Parameter: 4293 . B - where the copy is put 4294 4295 Level: intermediate 4296 4297 Notes: 4298 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4299 4300 `MatCopy()` copies the matrix entries of a matrix to another existing 4301 matrix (after first zeroing the second matrix). A related routine is 4302 `MatConvert()`, which first creates a new matrix and then copies the data. 4303 4304 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4305 @*/ 4306 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4307 { 4308 PetscInt i; 4309 4310 PetscFunctionBegin; 4311 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4312 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4313 PetscValidType(A, 1); 4314 PetscValidType(B, 2); 4315 PetscCheckSameComm(A, 1, B, 2); 4316 MatCheckPreallocated(B, 2); 4317 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4318 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4319 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")", A->rmap->N, B->rmap->N, 4320 A->cmap->N, B->cmap->N); 4321 MatCheckPreallocated(A, 1); 4322 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4323 4324 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4325 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4326 else PetscCall(MatCopy_Basic(A, B, str)); 4327 4328 B->stencil.dim = A->stencil.dim; 4329 B->stencil.noc = A->stencil.noc; 4330 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4331 B->stencil.dims[i] = A->stencil.dims[i]; 4332 B->stencil.starts[i] = A->stencil.starts[i]; 4333 } 4334 4335 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4336 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4337 PetscFunctionReturn(PETSC_SUCCESS); 4338 } 4339 4340 /*@ 4341 MatConvert - Converts a matrix to another matrix, either of the same 4342 or different type. 4343 4344 Collective 4345 4346 Input Parameters: 4347 + mat - the matrix 4348 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4349 same type as the original matrix. 4350 - reuse - denotes if the destination matrix is to be created or reused. 4351 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 4352 `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). 4353 4354 Output Parameter: 4355 . M - pointer to place new matrix 4356 4357 Level: intermediate 4358 4359 Notes: 4360 `MatConvert()` first creates a new matrix and then copies the data from 4361 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4362 entries of one matrix to another already existing matrix context. 4363 4364 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4365 the MPI communicator of the generated matrix is always the same as the communicator 4366 of the input matrix. 4367 4368 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4369 @*/ 4370 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4371 { 4372 PetscBool sametype, issame, flg; 4373 PetscBool3 issymmetric, ishermitian; 4374 char convname[256], mtype[256]; 4375 Mat B; 4376 4377 PetscFunctionBegin; 4378 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4379 PetscValidType(mat, 1); 4380 PetscAssertPointer(M, 4); 4381 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4382 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4383 MatCheckPreallocated(mat, 1); 4384 4385 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4386 if (flg) newtype = mtype; 4387 4388 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4389 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4390 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4391 if (reuse == MAT_REUSE_MATRIX) { 4392 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4393 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4394 } 4395 4396 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4397 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4398 PetscFunctionReturn(PETSC_SUCCESS); 4399 } 4400 4401 /* Cache Mat options because some converters use MatHeaderReplace */ 4402 issymmetric = mat->symmetric; 4403 ishermitian = mat->hermitian; 4404 4405 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4406 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4407 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4408 } else { 4409 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4410 const char *prefix[3] = {"seq", "mpi", ""}; 4411 PetscInt i; 4412 /* 4413 Order of precedence: 4414 0) See if newtype is a superclass of the current matrix. 4415 1) See if a specialized converter is known to the current matrix. 4416 2) See if a specialized converter is known to the desired matrix class. 4417 3) See if a good general converter is registered for the desired class 4418 (as of 6/27/03 only MATMPIADJ falls into this category). 4419 4) See if a good general converter is known for the current matrix. 4420 5) Use a really basic converter. 4421 */ 4422 4423 /* 0) See if newtype is a superclass of the current matrix. 4424 i.e mat is mpiaij and newtype is aij */ 4425 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4426 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4427 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4428 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4429 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4430 if (flg) { 4431 if (reuse == MAT_INPLACE_MATRIX) { 4432 PetscCall(PetscInfo(mat, "Early return\n")); 4433 PetscFunctionReturn(PETSC_SUCCESS); 4434 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4435 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4436 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4437 PetscFunctionReturn(PETSC_SUCCESS); 4438 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4439 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4440 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4441 PetscFunctionReturn(PETSC_SUCCESS); 4442 } 4443 } 4444 } 4445 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4446 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4447 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4448 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4449 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4450 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4451 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4452 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4453 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4454 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4455 if (conv) goto foundconv; 4456 } 4457 4458 /* 2) See if a specialized converter is known to the desired matrix class. */ 4459 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4460 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4461 PetscCall(MatSetType(B, newtype)); 4462 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4463 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4464 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4465 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4466 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4467 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4468 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4469 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4470 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4471 if (conv) { 4472 PetscCall(MatDestroy(&B)); 4473 goto foundconv; 4474 } 4475 } 4476 4477 /* 3) See if a good general converter is registered for the desired class */ 4478 conv = B->ops->convertfrom; 4479 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4480 PetscCall(MatDestroy(&B)); 4481 if (conv) goto foundconv; 4482 4483 /* 4) See if a good general converter is known for the current matrix */ 4484 if (mat->ops->convert) conv = mat->ops->convert; 4485 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4486 if (conv) goto foundconv; 4487 4488 /* 5) Use a really basic converter. */ 4489 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4490 conv = MatConvert_Basic; 4491 4492 foundconv: 4493 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4494 PetscCall((*conv)(mat, newtype, reuse, M)); 4495 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4496 /* the block sizes must be same if the mappings are copied over */ 4497 (*M)->rmap->bs = mat->rmap->bs; 4498 (*M)->cmap->bs = mat->cmap->bs; 4499 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4500 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4501 (*M)->rmap->mapping = mat->rmap->mapping; 4502 (*M)->cmap->mapping = mat->cmap->mapping; 4503 } 4504 (*M)->stencil.dim = mat->stencil.dim; 4505 (*M)->stencil.noc = mat->stencil.noc; 4506 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4507 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4508 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4509 } 4510 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4511 } 4512 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4513 4514 /* Copy Mat options */ 4515 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4516 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4517 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4518 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4519 PetscFunctionReturn(PETSC_SUCCESS); 4520 } 4521 4522 /*@ 4523 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4524 4525 Not Collective 4526 4527 Input Parameter: 4528 . mat - the matrix, must be a factored matrix 4529 4530 Output Parameter: 4531 . type - the string name of the package (do not free this string) 4532 4533 Level: intermediate 4534 4535 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4536 @*/ 4537 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4538 { 4539 PetscErrorCode (*conv)(Mat, MatSolverType *); 4540 4541 PetscFunctionBegin; 4542 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4543 PetscValidType(mat, 1); 4544 PetscAssertPointer(type, 2); 4545 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4546 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4547 if (conv) PetscCall((*conv)(mat, type)); 4548 else *type = MATSOLVERPETSC; 4549 PetscFunctionReturn(PETSC_SUCCESS); 4550 } 4551 4552 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4553 struct _MatSolverTypeForSpecifcType { 4554 MatType mtype; 4555 /* no entry for MAT_FACTOR_NONE */ 4556 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4557 MatSolverTypeForSpecifcType next; 4558 }; 4559 4560 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4561 struct _MatSolverTypeHolder { 4562 char *name; 4563 MatSolverTypeForSpecifcType handlers; 4564 MatSolverTypeHolder next; 4565 }; 4566 4567 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4568 4569 /*@C 4570 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4571 4572 Logically Collective, No Fortran Support 4573 4574 Input Parameters: 4575 + package - name of the package, for example `petsc` or `superlu` 4576 . mtype - the matrix type that works with this package 4577 . ftype - the type of factorization supported by the package 4578 - createfactor - routine that will create the factored matrix ready to be used 4579 4580 Level: developer 4581 4582 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4583 `MatGetFactor()` 4584 @*/ 4585 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4586 { 4587 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4588 PetscBool flg; 4589 MatSolverTypeForSpecifcType inext, iprev = NULL; 4590 4591 PetscFunctionBegin; 4592 PetscCall(MatInitializePackage()); 4593 if (!next) { 4594 PetscCall(PetscNew(&MatSolverTypeHolders)); 4595 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4596 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4597 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4598 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4599 PetscFunctionReturn(PETSC_SUCCESS); 4600 } 4601 while (next) { 4602 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4603 if (flg) { 4604 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4605 inext = next->handlers; 4606 while (inext) { 4607 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4608 if (flg) { 4609 inext->createfactor[(int)ftype - 1] = createfactor; 4610 PetscFunctionReturn(PETSC_SUCCESS); 4611 } 4612 iprev = inext; 4613 inext = inext->next; 4614 } 4615 PetscCall(PetscNew(&iprev->next)); 4616 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4617 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4618 PetscFunctionReturn(PETSC_SUCCESS); 4619 } 4620 prev = next; 4621 next = next->next; 4622 } 4623 PetscCall(PetscNew(&prev->next)); 4624 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4625 PetscCall(PetscNew(&prev->next->handlers)); 4626 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4627 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4628 PetscFunctionReturn(PETSC_SUCCESS); 4629 } 4630 4631 /*@C 4632 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4633 4634 Input Parameters: 4635 + type - name of the package, for example `petsc` or `superlu`, if this is 'NULL', then the first result that satisfies the other criteria is returned 4636 . ftype - the type of factorization supported by the type 4637 - mtype - the matrix type that works with this type 4638 4639 Output Parameters: 4640 + foundtype - `PETSC_TRUE` if the type was registered 4641 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4642 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4643 4644 Calling sequence of `createfactor`: 4645 + A - the matrix providing the factor matrix 4646 . ftype - the `MatFactorType` of the factor requested 4647 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4648 4649 Level: developer 4650 4651 Note: 4652 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4653 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4654 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4655 4656 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4657 `MatInitializePackage()` 4658 @*/ 4659 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4660 { 4661 MatSolverTypeHolder next = MatSolverTypeHolders; 4662 PetscBool flg; 4663 MatSolverTypeForSpecifcType inext; 4664 4665 PetscFunctionBegin; 4666 if (foundtype) *foundtype = PETSC_FALSE; 4667 if (foundmtype) *foundmtype = PETSC_FALSE; 4668 if (createfactor) *createfactor = NULL; 4669 4670 if (type) { 4671 while (next) { 4672 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4673 if (flg) { 4674 if (foundtype) *foundtype = PETSC_TRUE; 4675 inext = next->handlers; 4676 while (inext) { 4677 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4678 if (flg) { 4679 if (foundmtype) *foundmtype = PETSC_TRUE; 4680 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4681 PetscFunctionReturn(PETSC_SUCCESS); 4682 } 4683 inext = inext->next; 4684 } 4685 } 4686 next = next->next; 4687 } 4688 } else { 4689 while (next) { 4690 inext = next->handlers; 4691 while (inext) { 4692 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4693 if (flg && inext->createfactor[(int)ftype - 1]) { 4694 if (foundtype) *foundtype = PETSC_TRUE; 4695 if (foundmtype) *foundmtype = PETSC_TRUE; 4696 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4697 PetscFunctionReturn(PETSC_SUCCESS); 4698 } 4699 inext = inext->next; 4700 } 4701 next = next->next; 4702 } 4703 /* try with base classes inext->mtype */ 4704 next = MatSolverTypeHolders; 4705 while (next) { 4706 inext = next->handlers; 4707 while (inext) { 4708 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4709 if (flg && inext->createfactor[(int)ftype - 1]) { 4710 if (foundtype) *foundtype = PETSC_TRUE; 4711 if (foundmtype) *foundmtype = PETSC_TRUE; 4712 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4713 PetscFunctionReturn(PETSC_SUCCESS); 4714 } 4715 inext = inext->next; 4716 } 4717 next = next->next; 4718 } 4719 } 4720 PetscFunctionReturn(PETSC_SUCCESS); 4721 } 4722 4723 PetscErrorCode MatSolverTypeDestroy(void) 4724 { 4725 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4726 MatSolverTypeForSpecifcType inext, iprev; 4727 4728 PetscFunctionBegin; 4729 while (next) { 4730 PetscCall(PetscFree(next->name)); 4731 inext = next->handlers; 4732 while (inext) { 4733 PetscCall(PetscFree(inext->mtype)); 4734 iprev = inext; 4735 inext = inext->next; 4736 PetscCall(PetscFree(iprev)); 4737 } 4738 prev = next; 4739 next = next->next; 4740 PetscCall(PetscFree(prev)); 4741 } 4742 MatSolverTypeHolders = NULL; 4743 PetscFunctionReturn(PETSC_SUCCESS); 4744 } 4745 4746 /*@ 4747 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4748 4749 Logically Collective 4750 4751 Input Parameter: 4752 . mat - the matrix 4753 4754 Output Parameter: 4755 . flg - `PETSC_TRUE` if uses the ordering 4756 4757 Level: developer 4758 4759 Note: 4760 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4761 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4762 4763 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4764 @*/ 4765 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4766 { 4767 PetscFunctionBegin; 4768 *flg = mat->canuseordering; 4769 PetscFunctionReturn(PETSC_SUCCESS); 4770 } 4771 4772 /*@ 4773 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4774 4775 Logically Collective 4776 4777 Input Parameters: 4778 + mat - the matrix obtained with `MatGetFactor()` 4779 - ftype - the factorization type to be used 4780 4781 Output Parameter: 4782 . otype - the preferred ordering type 4783 4784 Level: developer 4785 4786 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4787 @*/ 4788 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4789 { 4790 PetscFunctionBegin; 4791 *otype = mat->preferredordering[ftype]; 4792 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4793 PetscFunctionReturn(PETSC_SUCCESS); 4794 } 4795 4796 /*@ 4797 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4798 4799 Collective 4800 4801 Input Parameters: 4802 + mat - the matrix 4803 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's solver if it is available), if this is 'NULL', then the first result that satisfies 4804 the other criteria is returned 4805 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4806 4807 Output Parameter: 4808 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4809 4810 Options Database Keys: 4811 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4812 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device 4813 - -pc_factor_mat_solve_on_host <bool> - do mat solve on host (with device matrices). Default is doing it on device 4814 4815 Level: intermediate 4816 4817 Notes: 4818 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4819 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4820 4821 Users usually access the factorization solvers via `KSP` 4822 4823 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4824 such as pastix, superlu, mumps etc. PETSc must have been ./configure to use the external solver, using the option --download-package or --with-package-dir 4825 4826 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4827 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4828 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4829 4830 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4831 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4832 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4833 4834 Developer Note: 4835 This should actually be called `MatCreateFactor()` since it creates a new factor object 4836 4837 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4838 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4839 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4840 @*/ 4841 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4842 { 4843 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4844 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4845 4846 PetscFunctionBegin; 4847 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4848 PetscValidType(mat, 1); 4849 4850 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4851 MatCheckPreallocated(mat, 1); 4852 4853 PetscCall(MatIsShell(mat, &shell)); 4854 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4855 if (hasop) { 4856 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4857 PetscFunctionReturn(PETSC_SUCCESS); 4858 } 4859 4860 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4861 if (!foundtype) { 4862 if (type) { 4863 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], 4864 ((PetscObject)mat)->type_name, type); 4865 } else { 4866 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); 4867 } 4868 } 4869 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4870 PetscCheck(conv, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support factorization type %s for matrix type %s", type, MatFactorTypes[ftype], ((PetscObject)mat)->type_name); 4871 4872 PetscCall((*conv)(mat, ftype, f)); 4873 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4874 PetscFunctionReturn(PETSC_SUCCESS); 4875 } 4876 4877 /*@ 4878 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4879 4880 Not Collective 4881 4882 Input Parameters: 4883 + mat - the matrix 4884 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default) 4885 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4886 4887 Output Parameter: 4888 . flg - PETSC_TRUE if the factorization is available 4889 4890 Level: intermediate 4891 4892 Notes: 4893 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4894 such as pastix, superlu, mumps etc. 4895 4896 PETSc must have been ./configure to use the external solver, using the option --download-package 4897 4898 Developer Note: 4899 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4900 4901 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4902 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4903 @*/ 4904 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4905 { 4906 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4907 4908 PetscFunctionBegin; 4909 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4910 PetscAssertPointer(flg, 4); 4911 4912 *flg = PETSC_FALSE; 4913 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4914 4915 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4916 MatCheckPreallocated(mat, 1); 4917 4918 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4919 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4920 PetscFunctionReturn(PETSC_SUCCESS); 4921 } 4922 4923 /*@ 4924 MatDuplicate - Duplicates a matrix including the non-zero structure. 4925 4926 Collective 4927 4928 Input Parameters: 4929 + mat - the matrix 4930 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4931 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4932 4933 Output Parameter: 4934 . M - pointer to place new matrix 4935 4936 Level: intermediate 4937 4938 Notes: 4939 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4940 4941 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4942 4943 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. 4944 4945 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4946 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4947 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4948 4949 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4950 @*/ 4951 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4952 { 4953 Mat B; 4954 VecType vtype; 4955 PetscInt i; 4956 PetscObject dm, container_h, container_d; 4957 void (*viewf)(void); 4958 4959 PetscFunctionBegin; 4960 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4961 PetscValidType(mat, 1); 4962 PetscAssertPointer(M, 3); 4963 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4964 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4965 MatCheckPreallocated(mat, 1); 4966 4967 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4968 PetscUseTypeMethod(mat, duplicate, op, M); 4969 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4970 B = *M; 4971 4972 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4973 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4974 PetscCall(MatGetVecType(mat, &vtype)); 4975 PetscCall(MatSetVecType(B, vtype)); 4976 4977 B->stencil.dim = mat->stencil.dim; 4978 B->stencil.noc = mat->stencil.noc; 4979 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4980 B->stencil.dims[i] = mat->stencil.dims[i]; 4981 B->stencil.starts[i] = mat->stencil.starts[i]; 4982 } 4983 4984 B->nooffproczerorows = mat->nooffproczerorows; 4985 B->nooffprocentries = mat->nooffprocentries; 4986 4987 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4988 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4989 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4990 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4991 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4992 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4993 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 4994 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4995 PetscFunctionReturn(PETSC_SUCCESS); 4996 } 4997 4998 /*@ 4999 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 5000 5001 Logically Collective 5002 5003 Input Parameter: 5004 . mat - the matrix 5005 5006 Output Parameter: 5007 . v - the diagonal of the matrix 5008 5009 Level: intermediate 5010 5011 Note: 5012 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5013 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5014 is larger than `ndiag`, the values of the remaining entries are unspecified. 5015 5016 Currently only correct in parallel for square matrices. 5017 5018 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5019 @*/ 5020 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5021 { 5022 PetscFunctionBegin; 5023 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5024 PetscValidType(mat, 1); 5025 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5026 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5027 MatCheckPreallocated(mat, 1); 5028 if (PetscDefined(USE_DEBUG)) { 5029 PetscInt nv, row, col, ndiag; 5030 5031 PetscCall(VecGetLocalSize(v, &nv)); 5032 PetscCall(MatGetLocalSize(mat, &row, &col)); 5033 ndiag = PetscMin(row, col); 5034 PetscCheck(nv >= ndiag, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming Mat and Vec. Vec local size %" PetscInt_FMT " < Mat local diagonal length %" PetscInt_FMT, nv, ndiag); 5035 } 5036 5037 PetscUseTypeMethod(mat, getdiagonal, v); 5038 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5039 PetscFunctionReturn(PETSC_SUCCESS); 5040 } 5041 5042 /*@ 5043 MatGetRowMin - Gets the minimum value (of the real part) of each 5044 row of the matrix 5045 5046 Logically Collective 5047 5048 Input Parameter: 5049 . mat - the matrix 5050 5051 Output Parameters: 5052 + v - the vector for storing the maximums 5053 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5054 5055 Level: intermediate 5056 5057 Note: 5058 The result of this call are the same as if one converted the matrix to dense format 5059 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5060 5061 This code is only implemented for a couple of matrix formats. 5062 5063 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5064 `MatGetRowMax()` 5065 @*/ 5066 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5067 { 5068 PetscFunctionBegin; 5069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5070 PetscValidType(mat, 1); 5071 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5072 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5073 5074 if (!mat->cmap->N) { 5075 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5076 if (idx) { 5077 PetscInt i, m = mat->rmap->n; 5078 for (i = 0; i < m; i++) idx[i] = -1; 5079 } 5080 } else { 5081 MatCheckPreallocated(mat, 1); 5082 } 5083 PetscUseTypeMethod(mat, getrowmin, v, idx); 5084 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5085 PetscFunctionReturn(PETSC_SUCCESS); 5086 } 5087 5088 /*@ 5089 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5090 row of the matrix 5091 5092 Logically Collective 5093 5094 Input Parameter: 5095 . mat - the matrix 5096 5097 Output Parameters: 5098 + v - the vector for storing the minimums 5099 - idx - the indices of the column found for each row (or `NULL` if not needed) 5100 5101 Level: intermediate 5102 5103 Notes: 5104 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5105 row is 0 (the first column). 5106 5107 This code is only implemented for a couple of matrix formats. 5108 5109 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5110 @*/ 5111 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5112 { 5113 PetscFunctionBegin; 5114 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5115 PetscValidType(mat, 1); 5116 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5117 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5118 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5119 5120 if (!mat->cmap->N) { 5121 PetscCall(VecSet(v, 0.0)); 5122 if (idx) { 5123 PetscInt i, m = mat->rmap->n; 5124 for (i = 0; i < m; i++) idx[i] = -1; 5125 } 5126 } else { 5127 MatCheckPreallocated(mat, 1); 5128 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5129 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5130 } 5131 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5132 PetscFunctionReturn(PETSC_SUCCESS); 5133 } 5134 5135 /*@ 5136 MatGetRowMax - Gets the maximum value (of the real part) of each 5137 row of the matrix 5138 5139 Logically Collective 5140 5141 Input Parameter: 5142 . mat - the matrix 5143 5144 Output Parameters: 5145 + v - the vector for storing the maximums 5146 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5147 5148 Level: intermediate 5149 5150 Notes: 5151 The result of this call are the same as if one converted the matrix to dense format 5152 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5153 5154 This code is only implemented for a couple of matrix formats. 5155 5156 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5157 @*/ 5158 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5159 { 5160 PetscFunctionBegin; 5161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5162 PetscValidType(mat, 1); 5163 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5164 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5165 5166 if (!mat->cmap->N) { 5167 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5168 if (idx) { 5169 PetscInt i, m = mat->rmap->n; 5170 for (i = 0; i < m; i++) idx[i] = -1; 5171 } 5172 } else { 5173 MatCheckPreallocated(mat, 1); 5174 PetscUseTypeMethod(mat, getrowmax, v, idx); 5175 } 5176 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5177 PetscFunctionReturn(PETSC_SUCCESS); 5178 } 5179 5180 /*@ 5181 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5182 row of the matrix 5183 5184 Logically Collective 5185 5186 Input Parameter: 5187 . mat - the matrix 5188 5189 Output Parameters: 5190 + v - the vector for storing the maximums 5191 - idx - the indices of the column found for each row (or `NULL` if not needed) 5192 5193 Level: intermediate 5194 5195 Notes: 5196 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5197 row is 0 (the first column). 5198 5199 This code is only implemented for a couple of matrix formats. 5200 5201 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5202 @*/ 5203 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5204 { 5205 PetscFunctionBegin; 5206 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5207 PetscValidType(mat, 1); 5208 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5209 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5210 5211 if (!mat->cmap->N) { 5212 PetscCall(VecSet(v, 0.0)); 5213 if (idx) { 5214 PetscInt i, m = mat->rmap->n; 5215 for (i = 0; i < m; i++) idx[i] = -1; 5216 } 5217 } else { 5218 MatCheckPreallocated(mat, 1); 5219 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5220 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5221 } 5222 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5223 PetscFunctionReturn(PETSC_SUCCESS); 5224 } 5225 5226 /*@ 5227 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5228 5229 Logically Collective 5230 5231 Input Parameter: 5232 . mat - the matrix 5233 5234 Output Parameter: 5235 . v - the vector for storing the sum 5236 5237 Level: intermediate 5238 5239 This code is only implemented for a couple of matrix formats. 5240 5241 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5242 @*/ 5243 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5244 { 5245 PetscFunctionBegin; 5246 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5247 PetscValidType(mat, 1); 5248 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5249 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5250 5251 if (!mat->cmap->N) { 5252 PetscCall(VecSet(v, 0.0)); 5253 } else { 5254 MatCheckPreallocated(mat, 1); 5255 PetscUseTypeMethod(mat, getrowsumabs, v); 5256 } 5257 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5258 PetscFunctionReturn(PETSC_SUCCESS); 5259 } 5260 5261 /*@ 5262 MatGetRowSum - Gets the sum of each row of the matrix 5263 5264 Logically or Neighborhood Collective 5265 5266 Input Parameter: 5267 . mat - the matrix 5268 5269 Output Parameter: 5270 . v - the vector for storing the sum of rows 5271 5272 Level: intermediate 5273 5274 Note: 5275 This code is slow since it is not currently specialized for different formats 5276 5277 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5278 @*/ 5279 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5280 { 5281 Vec ones; 5282 5283 PetscFunctionBegin; 5284 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5285 PetscValidType(mat, 1); 5286 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5287 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5288 MatCheckPreallocated(mat, 1); 5289 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5290 PetscCall(VecSet(ones, 1.)); 5291 PetscCall(MatMult(mat, ones, v)); 5292 PetscCall(VecDestroy(&ones)); 5293 PetscFunctionReturn(PETSC_SUCCESS); 5294 } 5295 5296 /*@ 5297 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5298 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5299 5300 Collective 5301 5302 Input Parameter: 5303 . mat - the matrix to provide the transpose 5304 5305 Output Parameter: 5306 . B - 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 5307 5308 Level: advanced 5309 5310 Note: 5311 Normally the use of `MatTranspose`(A, `MAT_REUSE_MATRIX`, &B) requires that `B` was obtained with a call to `MatTranspose`(A, `MAT_INITIAL_MATRIX`, &B). This 5312 routine allows bypassing that call. 5313 5314 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5315 @*/ 5316 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5317 { 5318 MatParentState *rb = NULL; 5319 5320 PetscFunctionBegin; 5321 PetscCall(PetscNew(&rb)); 5322 rb->id = ((PetscObject)mat)->id; 5323 rb->state = 0; 5324 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5325 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5326 PetscFunctionReturn(PETSC_SUCCESS); 5327 } 5328 5329 /*@ 5330 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5331 5332 Collective 5333 5334 Input Parameters: 5335 + mat - the matrix to transpose 5336 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5337 5338 Output Parameter: 5339 . B - the transpose of the matrix 5340 5341 Level: intermediate 5342 5343 Notes: 5344 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5345 5346 `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX` to store the transpose. If you already have a matrix to contain the 5347 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5348 5349 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. 5350 5351 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5352 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5353 5354 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5355 5356 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5357 5358 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5359 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5360 @*/ 5361 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5362 { 5363 PetscContainer rB = NULL; 5364 MatParentState *rb = NULL; 5365 5366 PetscFunctionBegin; 5367 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5368 PetscValidType(mat, 1); 5369 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5370 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5371 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5372 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5373 MatCheckPreallocated(mat, 1); 5374 if (reuse == MAT_REUSE_MATRIX) { 5375 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5376 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5377 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5378 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5379 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5380 } 5381 5382 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5383 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5384 PetscUseTypeMethod(mat, transpose, reuse, B); 5385 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5386 } 5387 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5388 5389 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5390 if (reuse != MAT_INPLACE_MATRIX) { 5391 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5392 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5393 rb->state = ((PetscObject)mat)->state; 5394 rb->nonzerostate = mat->nonzerostate; 5395 } 5396 PetscFunctionReturn(PETSC_SUCCESS); 5397 } 5398 5399 /*@ 5400 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5401 5402 Collective 5403 5404 Input Parameter: 5405 . A - the matrix to transpose 5406 5407 Output Parameter: 5408 . 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 5409 numerical portion. 5410 5411 Level: intermediate 5412 5413 Note: 5414 This is not supported for many matrix types, use `MatTranspose()` in those cases 5415 5416 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5417 @*/ 5418 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5419 { 5420 PetscFunctionBegin; 5421 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5422 PetscValidType(A, 1); 5423 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5424 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5425 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5426 PetscUseTypeMethod(A, transposesymbolic, B); 5427 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5428 5429 PetscCall(MatTransposeSetPrecursor(A, *B)); 5430 PetscFunctionReturn(PETSC_SUCCESS); 5431 } 5432 5433 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5434 { 5435 PetscContainer rB; 5436 MatParentState *rb; 5437 5438 PetscFunctionBegin; 5439 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5440 PetscValidType(A, 1); 5441 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5442 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5443 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5444 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5445 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5446 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5447 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5448 PetscFunctionReturn(PETSC_SUCCESS); 5449 } 5450 5451 /*@ 5452 MatIsTranspose - Test whether a matrix is another one's transpose, 5453 or its own, in which case it tests symmetry. 5454 5455 Collective 5456 5457 Input Parameters: 5458 + A - the matrix to test 5459 . B - the matrix to test against, this can equal the first parameter 5460 - tol - tolerance, differences between entries smaller than this are counted as zero 5461 5462 Output Parameter: 5463 . flg - the result 5464 5465 Level: intermediate 5466 5467 Notes: 5468 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5469 test involves parallel copies of the block off-diagonal parts of the matrix. 5470 5471 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5472 @*/ 5473 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5474 { 5475 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5476 5477 PetscFunctionBegin; 5478 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5479 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5480 PetscAssertPointer(flg, 4); 5481 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5482 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5483 *flg = PETSC_FALSE; 5484 if (f && g) { 5485 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5486 PetscCall((*f)(A, B, tol, flg)); 5487 } else { 5488 MatType mattype; 5489 5490 PetscCall(MatGetType(f ? B : A, &mattype)); 5491 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5492 } 5493 PetscFunctionReturn(PETSC_SUCCESS); 5494 } 5495 5496 /*@ 5497 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5498 5499 Collective 5500 5501 Input Parameters: 5502 + mat - the matrix to transpose and complex conjugate 5503 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5504 5505 Output Parameter: 5506 . B - the Hermitian transpose 5507 5508 Level: intermediate 5509 5510 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5511 @*/ 5512 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5513 { 5514 PetscFunctionBegin; 5515 PetscCall(MatTranspose(mat, reuse, B)); 5516 #if defined(PETSC_USE_COMPLEX) 5517 PetscCall(MatConjugate(*B)); 5518 #endif 5519 PetscFunctionReturn(PETSC_SUCCESS); 5520 } 5521 5522 /*@ 5523 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5524 5525 Collective 5526 5527 Input Parameters: 5528 + A - the matrix to test 5529 . B - the matrix to test against, this can equal the first parameter 5530 - tol - tolerance, differences between entries smaller than this are counted as zero 5531 5532 Output Parameter: 5533 . flg - the result 5534 5535 Level: intermediate 5536 5537 Notes: 5538 Only available for `MATAIJ` matrices. 5539 5540 The sequential algorithm 5541 has a running time of the order of the number of nonzeros; the parallel 5542 test involves parallel copies of the block off-diagonal parts of the matrix. 5543 5544 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5545 @*/ 5546 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5547 { 5548 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5549 5550 PetscFunctionBegin; 5551 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5552 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5553 PetscAssertPointer(flg, 4); 5554 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5555 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5556 if (f && g) { 5557 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5558 PetscCall((*f)(A, B, tol, flg)); 5559 } 5560 PetscFunctionReturn(PETSC_SUCCESS); 5561 } 5562 5563 /*@ 5564 MatPermute - Creates a new matrix with rows and columns permuted from the 5565 original. 5566 5567 Collective 5568 5569 Input Parameters: 5570 + mat - the matrix to permute 5571 . row - row permutation, each processor supplies only the permutation for its rows 5572 - col - column permutation, each processor supplies only the permutation for its columns 5573 5574 Output Parameter: 5575 . B - the permuted matrix 5576 5577 Level: advanced 5578 5579 Note: 5580 The index sets map from row/col of permuted matrix to row/col of original matrix. 5581 The index sets should be on the same communicator as mat and have the same local sizes. 5582 5583 Developer Note: 5584 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5585 exploit the fact that row and col are permutations, consider implementing the 5586 more general `MatCreateSubMatrix()` instead. 5587 5588 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5589 @*/ 5590 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5591 { 5592 PetscFunctionBegin; 5593 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5594 PetscValidType(mat, 1); 5595 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5596 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5597 PetscAssertPointer(B, 4); 5598 PetscCheckSameComm(mat, 1, row, 2); 5599 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5600 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5601 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5602 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5603 MatCheckPreallocated(mat, 1); 5604 5605 if (mat->ops->permute) { 5606 PetscUseTypeMethod(mat, permute, row, col, B); 5607 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5608 } else { 5609 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5610 } 5611 PetscFunctionReturn(PETSC_SUCCESS); 5612 } 5613 5614 /*@ 5615 MatEqual - Compares two matrices. 5616 5617 Collective 5618 5619 Input Parameters: 5620 + A - the first matrix 5621 - B - the second matrix 5622 5623 Output Parameter: 5624 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5625 5626 Level: intermediate 5627 5628 Note: 5629 If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing the results of several matrix-vector product 5630 using several randomly created vectors, see `MatMultEqual()`. 5631 5632 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5633 @*/ 5634 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5635 { 5636 PetscFunctionBegin; 5637 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5638 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5639 PetscValidType(A, 1); 5640 PetscValidType(B, 2); 5641 PetscAssertPointer(flg, 3); 5642 PetscCheckSameComm(A, 1, B, 2); 5643 MatCheckPreallocated(A, 1); 5644 MatCheckPreallocated(B, 2); 5645 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5646 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5647 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N, 5648 B->cmap->N); 5649 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5650 PetscUseTypeMethod(A, equal, B, flg); 5651 } else { 5652 PetscCall(MatMultEqual(A, B, 10, flg)); 5653 } 5654 PetscFunctionReturn(PETSC_SUCCESS); 5655 } 5656 5657 /*@ 5658 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5659 matrices that are stored as vectors. Either of the two scaling 5660 matrices can be `NULL`. 5661 5662 Collective 5663 5664 Input Parameters: 5665 + mat - the matrix to be scaled 5666 . l - the left scaling vector (or `NULL`) 5667 - r - the right scaling vector (or `NULL`) 5668 5669 Level: intermediate 5670 5671 Note: 5672 `MatDiagonalScale()` computes $A = LAR$, where 5673 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5674 The L scales the rows of the matrix, the R scales the columns of the matrix. 5675 5676 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5677 @*/ 5678 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5679 { 5680 PetscFunctionBegin; 5681 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5682 PetscValidType(mat, 1); 5683 if (l) { 5684 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5685 PetscCheckSameComm(mat, 1, l, 2); 5686 } 5687 if (r) { 5688 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5689 PetscCheckSameComm(mat, 1, r, 3); 5690 } 5691 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5692 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5693 MatCheckPreallocated(mat, 1); 5694 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5695 5696 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5697 PetscUseTypeMethod(mat, diagonalscale, l, r); 5698 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5699 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5700 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5701 PetscFunctionReturn(PETSC_SUCCESS); 5702 } 5703 5704 /*@ 5705 MatScale - Scales all elements of a matrix by a given number. 5706 5707 Logically Collective 5708 5709 Input Parameters: 5710 + mat - the matrix to be scaled 5711 - a - the scaling value 5712 5713 Level: intermediate 5714 5715 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5716 @*/ 5717 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5718 { 5719 PetscFunctionBegin; 5720 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5721 PetscValidType(mat, 1); 5722 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5723 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5724 PetscValidLogicalCollectiveScalar(mat, a, 2); 5725 MatCheckPreallocated(mat, 1); 5726 5727 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5728 if (a != (PetscScalar)1.0) { 5729 PetscUseTypeMethod(mat, scale, a); 5730 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5731 } 5732 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5733 PetscFunctionReturn(PETSC_SUCCESS); 5734 } 5735 5736 /*@ 5737 MatNorm - Calculates various norms of a matrix. 5738 5739 Collective 5740 5741 Input Parameters: 5742 + mat - the matrix 5743 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5744 5745 Output Parameter: 5746 . nrm - the resulting norm 5747 5748 Level: intermediate 5749 5750 .seealso: [](ch_matrices), `Mat` 5751 @*/ 5752 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5753 { 5754 PetscFunctionBegin; 5755 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5756 PetscValidType(mat, 1); 5757 PetscAssertPointer(nrm, 3); 5758 5759 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5760 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5761 MatCheckPreallocated(mat, 1); 5762 5763 PetscUseTypeMethod(mat, norm, type, nrm); 5764 PetscFunctionReturn(PETSC_SUCCESS); 5765 } 5766 5767 /* 5768 This variable is used to prevent counting of MatAssemblyBegin() that 5769 are called from within a MatAssemblyEnd(). 5770 */ 5771 static PetscInt MatAssemblyEnd_InUse = 0; 5772 /*@ 5773 MatAssemblyBegin - Begins assembling the matrix. This routine should 5774 be called after completing all calls to `MatSetValues()`. 5775 5776 Collective 5777 5778 Input Parameters: 5779 + mat - the matrix 5780 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5781 5782 Level: beginner 5783 5784 Notes: 5785 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5786 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5787 5788 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5789 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5790 using the matrix. 5791 5792 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5793 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 5794 a global collective operation requiring all processes that share the matrix. 5795 5796 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5797 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5798 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5799 5800 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5801 @*/ 5802 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5803 { 5804 PetscFunctionBegin; 5805 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5806 PetscValidType(mat, 1); 5807 MatCheckPreallocated(mat, 1); 5808 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5809 if (mat->assembled) { 5810 mat->was_assembled = PETSC_TRUE; 5811 mat->assembled = PETSC_FALSE; 5812 } 5813 5814 if (!MatAssemblyEnd_InUse) { 5815 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5816 PetscTryTypeMethod(mat, assemblybegin, type); 5817 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5818 } else PetscTryTypeMethod(mat, assemblybegin, type); 5819 PetscFunctionReturn(PETSC_SUCCESS); 5820 } 5821 5822 /*@ 5823 MatAssembled - Indicates if a matrix has been assembled and is ready for 5824 use; for example, in matrix-vector product. 5825 5826 Not Collective 5827 5828 Input Parameter: 5829 . mat - the matrix 5830 5831 Output Parameter: 5832 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5833 5834 Level: advanced 5835 5836 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5837 @*/ 5838 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5839 { 5840 PetscFunctionBegin; 5841 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5842 PetscAssertPointer(assembled, 2); 5843 *assembled = mat->assembled; 5844 PetscFunctionReturn(PETSC_SUCCESS); 5845 } 5846 5847 /*@ 5848 MatAssemblyEnd - Completes assembling the matrix. This routine should 5849 be called after `MatAssemblyBegin()`. 5850 5851 Collective 5852 5853 Input Parameters: 5854 + mat - the matrix 5855 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5856 5857 Options Database Keys: 5858 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5859 . -mat_view ::ascii_info_detail - Prints more detailed info 5860 . -mat_view - Prints matrix in ASCII format 5861 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5862 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5863 . -display <name> - Sets display name (default is host) 5864 . -draw_pause <sec> - Sets number of seconds to pause after display 5865 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5866 . -viewer_socket_machine <machine> - Machine to use for socket 5867 . -viewer_socket_port <port> - Port number to use for socket 5868 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5869 5870 Level: beginner 5871 5872 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5873 @*/ 5874 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5875 { 5876 static PetscInt inassm = 0; 5877 PetscBool flg = PETSC_FALSE; 5878 5879 PetscFunctionBegin; 5880 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5881 PetscValidType(mat, 1); 5882 5883 inassm++; 5884 MatAssemblyEnd_InUse++; 5885 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5886 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5887 PetscTryTypeMethod(mat, assemblyend, type); 5888 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5889 } else PetscTryTypeMethod(mat, assemblyend, type); 5890 5891 /* Flush assembly is not a true assembly */ 5892 if (type != MAT_FLUSH_ASSEMBLY) { 5893 if (mat->num_ass) { 5894 if (!mat->symmetry_eternal) { 5895 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5896 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5897 } 5898 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5899 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5900 } 5901 mat->num_ass++; 5902 mat->assembled = PETSC_TRUE; 5903 mat->ass_nonzerostate = mat->nonzerostate; 5904 } 5905 5906 mat->insertmode = NOT_SET_VALUES; 5907 MatAssemblyEnd_InUse--; 5908 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5909 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5910 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5911 5912 if (mat->checksymmetryonassembly) { 5913 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5914 if (flg) { 5915 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5916 } else { 5917 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5918 } 5919 } 5920 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5921 } 5922 inassm--; 5923 PetscFunctionReturn(PETSC_SUCCESS); 5924 } 5925 5926 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5927 /*@ 5928 MatSetOption - Sets a parameter option for a matrix. Some options 5929 may be specific to certain storage formats. Some options 5930 determine how values will be inserted (or added). Sorted, 5931 row-oriented input will generally assemble the fastest. The default 5932 is row-oriented. 5933 5934 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5935 5936 Input Parameters: 5937 + mat - the matrix 5938 . op - the option, one of those listed below (and possibly others), 5939 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5940 5941 Options Describing Matrix Structure: 5942 + `MAT_SPD` - symmetric positive definite 5943 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5944 . `MAT_HERMITIAN` - transpose is the complex conjugation 5945 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5946 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5947 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5948 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5949 5950 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5951 do not need to be computed (usually at a high cost) 5952 5953 Options For Use with `MatSetValues()`: 5954 Insert a logically dense subblock, which can be 5955 . `MAT_ROW_ORIENTED` - row-oriented (default) 5956 5957 These options reflect the data you pass in with `MatSetValues()`; it has 5958 nothing to do with how the data is stored internally in the matrix 5959 data structure. 5960 5961 When (re)assembling a matrix, we can restrict the input for 5962 efficiency/debugging purposes. These options include 5963 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5964 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5965 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5966 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5967 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5968 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5969 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5970 performance for very large process counts. 5971 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5972 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5973 functions, instead sending only neighbor messages. 5974 5975 Level: intermediate 5976 5977 Notes: 5978 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5979 5980 Some options are relevant only for particular matrix types and 5981 are thus ignored by others. Other options are not supported by 5982 certain matrix types and will generate an error message if set. 5983 5984 If using Fortran to compute a matrix, one may need to 5985 use the column-oriented option (or convert to the row-oriented 5986 format). 5987 5988 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5989 that would generate a new entry in the nonzero structure is instead 5990 ignored. Thus, if memory has not already been allocated for this particular 5991 data, then the insertion is ignored. For dense matrices, in which 5992 the entire array is allocated, no entries are ever ignored. 5993 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5994 5995 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5996 that would generate a new entry in the nonzero structure instead produces 5997 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 5998 5999 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6000 that would generate a new entry that has not been preallocated will 6001 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6002 only.) This is a useful flag when debugging matrix memory preallocation. 6003 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6004 6005 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6006 other processors should be dropped, rather than stashed. 6007 This is useful if you know that the "owning" processor is also 6008 always generating the correct matrix entries, so that PETSc need 6009 not transfer duplicate entries generated on another processor. 6010 6011 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6012 searches during matrix assembly. When this flag is set, the hash table 6013 is created during the first matrix assembly. This hash table is 6014 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6015 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6016 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6017 supported by `MATMPIBAIJ` format only. 6018 6019 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6020 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6021 6022 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6023 a zero location in the matrix 6024 6025 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6026 6027 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6028 zero row routines and thus improves performance for very large process counts. 6029 6030 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6031 part of the matrix (since they should match the upper triangular part). 6032 6033 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6034 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6035 with finite difference schemes with non-periodic boundary conditions. 6036 6037 Developer Note: 6038 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6039 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6040 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6041 not changed. 6042 6043 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6044 @*/ 6045 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6046 { 6047 PetscFunctionBegin; 6048 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6049 if (op > 0) { 6050 PetscValidLogicalCollectiveEnum(mat, op, 2); 6051 PetscValidLogicalCollectiveBool(mat, flg, 3); 6052 } 6053 6054 PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op); 6055 6056 switch (op) { 6057 case MAT_FORCE_DIAGONAL_ENTRIES: 6058 mat->force_diagonals = flg; 6059 PetscFunctionReturn(PETSC_SUCCESS); 6060 case MAT_NO_OFF_PROC_ENTRIES: 6061 mat->nooffprocentries = flg; 6062 PetscFunctionReturn(PETSC_SUCCESS); 6063 case MAT_SUBSET_OFF_PROC_ENTRIES: 6064 mat->assembly_subset = flg; 6065 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6066 #if !defined(PETSC_HAVE_MPIUNI) 6067 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6068 #endif 6069 mat->stash.first_assembly_done = PETSC_FALSE; 6070 } 6071 PetscFunctionReturn(PETSC_SUCCESS); 6072 case MAT_NO_OFF_PROC_ZERO_ROWS: 6073 mat->nooffproczerorows = flg; 6074 PetscFunctionReturn(PETSC_SUCCESS); 6075 case MAT_SPD: 6076 if (flg) { 6077 mat->spd = PETSC_BOOL3_TRUE; 6078 mat->symmetric = PETSC_BOOL3_TRUE; 6079 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6080 } else { 6081 mat->spd = PETSC_BOOL3_FALSE; 6082 } 6083 break; 6084 case MAT_SYMMETRIC: 6085 mat->symmetric = PetscBoolToBool3(flg); 6086 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6087 #if !defined(PETSC_USE_COMPLEX) 6088 mat->hermitian = PetscBoolToBool3(flg); 6089 #endif 6090 break; 6091 case MAT_HERMITIAN: 6092 mat->hermitian = PetscBoolToBool3(flg); 6093 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6094 #if !defined(PETSC_USE_COMPLEX) 6095 mat->symmetric = PetscBoolToBool3(flg); 6096 #endif 6097 break; 6098 case MAT_STRUCTURALLY_SYMMETRIC: 6099 mat->structurally_symmetric = PetscBoolToBool3(flg); 6100 break; 6101 case MAT_SYMMETRY_ETERNAL: 6102 PetscCheck(mat->symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SYMMETRY_ETERNAL without first setting MAT_SYMMETRIC to true or false"); 6103 mat->symmetry_eternal = flg; 6104 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6105 break; 6106 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6107 PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURALLY_SYMMETRIC to true or false"); 6108 mat->structural_symmetry_eternal = flg; 6109 break; 6110 case MAT_SPD_ETERNAL: 6111 PetscCheck(mat->spd != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SPD_ETERNAL without first setting MAT_SPD to true or false"); 6112 mat->spd_eternal = flg; 6113 if (flg) { 6114 mat->structural_symmetry_eternal = PETSC_TRUE; 6115 mat->symmetry_eternal = PETSC_TRUE; 6116 } 6117 break; 6118 case MAT_STRUCTURE_ONLY: 6119 mat->structure_only = flg; 6120 break; 6121 case MAT_SORTED_FULL: 6122 mat->sortedfull = flg; 6123 break; 6124 default: 6125 break; 6126 } 6127 PetscTryTypeMethod(mat, setoption, op, flg); 6128 PetscFunctionReturn(PETSC_SUCCESS); 6129 } 6130 6131 /*@ 6132 MatGetOption - Gets a parameter option that has been set for a matrix. 6133 6134 Logically Collective 6135 6136 Input Parameters: 6137 + mat - the matrix 6138 - op - the option, this only responds to certain options, check the code for which ones 6139 6140 Output Parameter: 6141 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6142 6143 Level: intermediate 6144 6145 Notes: 6146 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6147 6148 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6149 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6150 6151 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6152 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6153 @*/ 6154 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6155 { 6156 PetscFunctionBegin; 6157 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6158 PetscValidType(mat, 1); 6159 6160 PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op); 6161 PetscCheck(((PetscObject)mat)->type_name, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_TYPENOTSET, "Cannot get options until type and size have been set, see MatSetType() and MatSetSizes()"); 6162 6163 switch (op) { 6164 case MAT_NO_OFF_PROC_ENTRIES: 6165 *flg = mat->nooffprocentries; 6166 break; 6167 case MAT_NO_OFF_PROC_ZERO_ROWS: 6168 *flg = mat->nooffproczerorows; 6169 break; 6170 case MAT_SYMMETRIC: 6171 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6172 break; 6173 case MAT_HERMITIAN: 6174 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6175 break; 6176 case MAT_STRUCTURALLY_SYMMETRIC: 6177 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6178 break; 6179 case MAT_SPD: 6180 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6181 break; 6182 case MAT_SYMMETRY_ETERNAL: 6183 *flg = mat->symmetry_eternal; 6184 break; 6185 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6186 *flg = mat->symmetry_eternal; 6187 break; 6188 default: 6189 break; 6190 } 6191 PetscFunctionReturn(PETSC_SUCCESS); 6192 } 6193 6194 /*@ 6195 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6196 this routine retains the old nonzero structure. 6197 6198 Logically Collective 6199 6200 Input Parameter: 6201 . mat - the matrix 6202 6203 Level: intermediate 6204 6205 Note: 6206 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. 6207 See the Performance chapter of the users manual for information on preallocating matrices. 6208 6209 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6210 @*/ 6211 PetscErrorCode MatZeroEntries(Mat mat) 6212 { 6213 PetscFunctionBegin; 6214 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6215 PetscValidType(mat, 1); 6216 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6217 PetscCheck(mat->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for matrices where you have set values but not yet assembled"); 6218 MatCheckPreallocated(mat, 1); 6219 6220 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6221 PetscUseTypeMethod(mat, zeroentries); 6222 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6223 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6224 PetscFunctionReturn(PETSC_SUCCESS); 6225 } 6226 6227 /*@ 6228 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6229 of a set of rows and columns of a matrix. 6230 6231 Collective 6232 6233 Input Parameters: 6234 + mat - the matrix 6235 . numRows - the number of rows/columns to zero 6236 . rows - the global row indices 6237 . diag - value put in the diagonal of the eliminated rows 6238 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6239 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6240 6241 Level: intermediate 6242 6243 Notes: 6244 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6245 6246 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6247 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 6248 6249 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6250 Krylov method to take advantage of the known solution on the zeroed rows. 6251 6252 For the parallel case, all processes that share the matrix (i.e., 6253 those in the communicator used for matrix creation) MUST call this 6254 routine, regardless of whether any rows being zeroed are owned by 6255 them. 6256 6257 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6258 removes them from the nonzero pattern. The nonzero pattern of the matrix can still change if a nonzero needs to be inserted on a diagonal entry that was previously 6259 missing. 6260 6261 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6262 list only rows local to itself). 6263 6264 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6265 6266 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6267 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6268 @*/ 6269 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6270 { 6271 PetscFunctionBegin; 6272 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6273 PetscValidType(mat, 1); 6274 if (numRows) PetscAssertPointer(rows, 3); 6275 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6276 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6277 MatCheckPreallocated(mat, 1); 6278 6279 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6280 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6281 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6282 PetscFunctionReturn(PETSC_SUCCESS); 6283 } 6284 6285 /*@ 6286 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6287 of a set of rows and columns of a matrix. 6288 6289 Collective 6290 6291 Input Parameters: 6292 + mat - the matrix 6293 . is - the rows to zero 6294 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6295 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6296 - b - optional vector of right-hand side, that will be adjusted by provided solution 6297 6298 Level: intermediate 6299 6300 Note: 6301 See `MatZeroRowsColumns()` for details on how this routine operates. 6302 6303 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6304 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6305 @*/ 6306 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6307 { 6308 PetscInt numRows; 6309 const PetscInt *rows; 6310 6311 PetscFunctionBegin; 6312 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6313 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6314 PetscValidType(mat, 1); 6315 PetscValidType(is, 2); 6316 PetscCall(ISGetLocalSize(is, &numRows)); 6317 PetscCall(ISGetIndices(is, &rows)); 6318 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6319 PetscCall(ISRestoreIndices(is, &rows)); 6320 PetscFunctionReturn(PETSC_SUCCESS); 6321 } 6322 6323 /*@ 6324 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6325 of a set of rows of a matrix. 6326 6327 Collective 6328 6329 Input Parameters: 6330 + mat - the matrix 6331 . numRows - the number of rows to zero 6332 . rows - the global row indices 6333 . diag - value put in the diagonal of the zeroed rows 6334 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6335 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6336 6337 Level: intermediate 6338 6339 Notes: 6340 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6341 6342 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6343 6344 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6345 Krylov method to take advantage of the known solution on the zeroed rows. 6346 6347 May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reduced problem (`PCDISTRIBUTE` completely eliminates the zeroed rows and their corresponding columns) 6348 from the matrix. 6349 6350 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6351 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6352 formats this does not alter the nonzero structure. 6353 6354 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6355 of the matrix is not changed the values are 6356 merely zeroed. 6357 6358 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6359 formats can optionally remove the main diagonal entry from the 6360 nonzero structure as well, by passing 0.0 as the final argument). 6361 6362 For the parallel case, all processes that share the matrix (i.e., 6363 those in the communicator used for matrix creation) MUST call this 6364 routine, regardless of whether any rows being zeroed are owned by 6365 them. 6366 6367 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6368 list only rows local to itself). 6369 6370 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6371 owns that are to be zeroed. This saves a global synchronization in the implementation. 6372 6373 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6374 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6375 @*/ 6376 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6377 { 6378 PetscFunctionBegin; 6379 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6380 PetscValidType(mat, 1); 6381 if (numRows) PetscAssertPointer(rows, 3); 6382 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6383 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6384 MatCheckPreallocated(mat, 1); 6385 6386 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6387 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6388 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6389 PetscFunctionReturn(PETSC_SUCCESS); 6390 } 6391 6392 /*@ 6393 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6394 of a set of rows of a matrix indicated by an `IS` 6395 6396 Collective 6397 6398 Input Parameters: 6399 + mat - the matrix 6400 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6401 . diag - value put in all diagonals of eliminated rows 6402 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6403 - b - optional vector of right-hand side, that will be adjusted by provided solution 6404 6405 Level: intermediate 6406 6407 Note: 6408 See `MatZeroRows()` for details on how this routine operates. 6409 6410 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6411 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6412 @*/ 6413 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6414 { 6415 PetscInt numRows = 0; 6416 const PetscInt *rows = NULL; 6417 6418 PetscFunctionBegin; 6419 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6420 PetscValidType(mat, 1); 6421 if (is) { 6422 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6423 PetscCall(ISGetLocalSize(is, &numRows)); 6424 PetscCall(ISGetIndices(is, &rows)); 6425 } 6426 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6427 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6428 PetscFunctionReturn(PETSC_SUCCESS); 6429 } 6430 6431 /*@ 6432 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6433 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6434 6435 Collective 6436 6437 Input Parameters: 6438 + mat - the matrix 6439 . numRows - the number of rows to remove 6440 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6441 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6442 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6443 - b - optional vector of right-hand side, that will be adjusted by provided solution 6444 6445 Level: intermediate 6446 6447 Notes: 6448 See `MatZeroRows()` for details on how this routine operates. 6449 6450 The grid coordinates are across the entire grid, not just the local portion 6451 6452 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6453 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6454 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6455 `DM_BOUNDARY_PERIODIC` boundary type. 6456 6457 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 6458 a single value per point) you can skip filling those indices. 6459 6460 Fortran Note: 6461 `idxm` and `idxn` should be declared as 6462 .vb 6463 MatStencil idxm(4, m) 6464 .ve 6465 and the values inserted using 6466 .vb 6467 idxm(MatStencil_i, 1) = i 6468 idxm(MatStencil_j, 1) = j 6469 idxm(MatStencil_k, 1) = k 6470 idxm(MatStencil_c, 1) = c 6471 etc 6472 .ve 6473 6474 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6475 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6476 @*/ 6477 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6478 { 6479 PetscInt dim = mat->stencil.dim; 6480 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6481 PetscInt *dims = mat->stencil.dims + 1; 6482 PetscInt *starts = mat->stencil.starts; 6483 PetscInt *dxm = (PetscInt *)rows; 6484 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6485 6486 PetscFunctionBegin; 6487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6488 PetscValidType(mat, 1); 6489 if (numRows) PetscAssertPointer(rows, 3); 6490 6491 PetscCall(PetscMalloc1(numRows, &jdxm)); 6492 for (i = 0; i < numRows; ++i) { 6493 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6494 for (j = 0; j < 3 - sdim; ++j) dxm++; 6495 /* Local index in X dir */ 6496 tmp = *dxm++ - starts[0]; 6497 /* Loop over remaining dimensions */ 6498 for (j = 0; j < dim - 1; ++j) { 6499 /* If nonlocal, set index to be negative */ 6500 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6501 /* Update local index */ 6502 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6503 } 6504 /* Skip component slot if necessary */ 6505 if (mat->stencil.noc) dxm++; 6506 /* Local row number */ 6507 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6508 } 6509 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6510 PetscCall(PetscFree(jdxm)); 6511 PetscFunctionReturn(PETSC_SUCCESS); 6512 } 6513 6514 /*@ 6515 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6516 of a set of rows and columns of a matrix. 6517 6518 Collective 6519 6520 Input Parameters: 6521 + mat - the matrix 6522 . numRows - the number of rows/columns to remove 6523 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6524 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6525 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6526 - b - optional vector of right-hand side, that will be adjusted by provided solution 6527 6528 Level: intermediate 6529 6530 Notes: 6531 See `MatZeroRowsColumns()` for details on how this routine operates. 6532 6533 The grid coordinates are across the entire grid, not just the local portion 6534 6535 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6536 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6537 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6538 `DM_BOUNDARY_PERIODIC` boundary type. 6539 6540 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 6541 a single value per point) you can skip filling those indices. 6542 6543 Fortran Note: 6544 `idxm` and `idxn` should be declared as 6545 .vb 6546 MatStencil idxm(4, m) 6547 .ve 6548 and the values inserted using 6549 .vb 6550 idxm(MatStencil_i, 1) = i 6551 idxm(MatStencil_j, 1) = j 6552 idxm(MatStencil_k, 1) = k 6553 idxm(MatStencil_c, 1) = c 6554 etc 6555 .ve 6556 6557 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6558 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6559 @*/ 6560 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6561 { 6562 PetscInt dim = mat->stencil.dim; 6563 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6564 PetscInt *dims = mat->stencil.dims + 1; 6565 PetscInt *starts = mat->stencil.starts; 6566 PetscInt *dxm = (PetscInt *)rows; 6567 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6568 6569 PetscFunctionBegin; 6570 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6571 PetscValidType(mat, 1); 6572 if (numRows) PetscAssertPointer(rows, 3); 6573 6574 PetscCall(PetscMalloc1(numRows, &jdxm)); 6575 for (i = 0; i < numRows; ++i) { 6576 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6577 for (j = 0; j < 3 - sdim; ++j) dxm++; 6578 /* Local index in X dir */ 6579 tmp = *dxm++ - starts[0]; 6580 /* Loop over remaining dimensions */ 6581 for (j = 0; j < dim - 1; ++j) { 6582 /* If nonlocal, set index to be negative */ 6583 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6584 /* Update local index */ 6585 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6586 } 6587 /* Skip component slot if necessary */ 6588 if (mat->stencil.noc) dxm++; 6589 /* Local row number */ 6590 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6591 } 6592 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6593 PetscCall(PetscFree(jdxm)); 6594 PetscFunctionReturn(PETSC_SUCCESS); 6595 } 6596 6597 /*@ 6598 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6599 of a set of rows of a matrix; using local numbering of rows. 6600 6601 Collective 6602 6603 Input Parameters: 6604 + mat - the matrix 6605 . numRows - the number of rows to remove 6606 . rows - the local row indices 6607 . diag - value put in all diagonals of eliminated rows 6608 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6609 - b - optional vector of right-hand side, that will be adjusted by provided solution 6610 6611 Level: intermediate 6612 6613 Notes: 6614 Before calling `MatZeroRowsLocal()`, the user must first set the 6615 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6616 6617 See `MatZeroRows()` for details on how this routine operates. 6618 6619 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6620 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6621 @*/ 6622 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6623 { 6624 PetscFunctionBegin; 6625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6626 PetscValidType(mat, 1); 6627 if (numRows) PetscAssertPointer(rows, 3); 6628 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6629 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6630 MatCheckPreallocated(mat, 1); 6631 6632 if (mat->ops->zerorowslocal) { 6633 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6634 } else { 6635 IS is, newis; 6636 const PetscInt *newRows; 6637 6638 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6639 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6640 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6641 PetscCall(ISGetIndices(newis, &newRows)); 6642 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6643 PetscCall(ISRestoreIndices(newis, &newRows)); 6644 PetscCall(ISDestroy(&newis)); 6645 PetscCall(ISDestroy(&is)); 6646 } 6647 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6648 PetscFunctionReturn(PETSC_SUCCESS); 6649 } 6650 6651 /*@ 6652 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6653 of a set of rows of a matrix; using local numbering of rows. 6654 6655 Collective 6656 6657 Input Parameters: 6658 + mat - the matrix 6659 . is - index set of rows to remove 6660 . diag - value put in all diagonals of eliminated rows 6661 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6662 - b - optional vector of right-hand side, that will be adjusted by provided solution 6663 6664 Level: intermediate 6665 6666 Notes: 6667 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6668 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6669 6670 See `MatZeroRows()` for details on how this routine operates. 6671 6672 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6673 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6674 @*/ 6675 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6676 { 6677 PetscInt numRows; 6678 const PetscInt *rows; 6679 6680 PetscFunctionBegin; 6681 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6682 PetscValidType(mat, 1); 6683 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6684 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6685 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6686 MatCheckPreallocated(mat, 1); 6687 6688 PetscCall(ISGetLocalSize(is, &numRows)); 6689 PetscCall(ISGetIndices(is, &rows)); 6690 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6691 PetscCall(ISRestoreIndices(is, &rows)); 6692 PetscFunctionReturn(PETSC_SUCCESS); 6693 } 6694 6695 /*@ 6696 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6697 of a set of rows and columns of a matrix; using local numbering of rows. 6698 6699 Collective 6700 6701 Input Parameters: 6702 + mat - the matrix 6703 . numRows - the number of rows to remove 6704 . rows - the global row indices 6705 . diag - value put in all diagonals of eliminated rows 6706 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6707 - b - optional vector of right-hand side, that will be adjusted by provided solution 6708 6709 Level: intermediate 6710 6711 Notes: 6712 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6713 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6714 6715 See `MatZeroRowsColumns()` for details on how this routine operates. 6716 6717 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6718 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6719 @*/ 6720 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6721 { 6722 IS is, newis; 6723 const PetscInt *newRows; 6724 6725 PetscFunctionBegin; 6726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6727 PetscValidType(mat, 1); 6728 if (numRows) PetscAssertPointer(rows, 3); 6729 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6730 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6731 MatCheckPreallocated(mat, 1); 6732 6733 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6734 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6735 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6736 PetscCall(ISGetIndices(newis, &newRows)); 6737 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6738 PetscCall(ISRestoreIndices(newis, &newRows)); 6739 PetscCall(ISDestroy(&newis)); 6740 PetscCall(ISDestroy(&is)); 6741 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6742 PetscFunctionReturn(PETSC_SUCCESS); 6743 } 6744 6745 /*@ 6746 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6747 of a set of rows and columns of a matrix; using local numbering of rows. 6748 6749 Collective 6750 6751 Input Parameters: 6752 + mat - the matrix 6753 . is - index set of rows to remove 6754 . diag - value put in all diagonals of eliminated rows 6755 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6756 - b - optional vector of right-hand side, that will be adjusted by provided solution 6757 6758 Level: intermediate 6759 6760 Notes: 6761 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6762 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6763 6764 See `MatZeroRowsColumns()` for details on how this routine operates. 6765 6766 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6767 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6768 @*/ 6769 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6770 { 6771 PetscInt numRows; 6772 const PetscInt *rows; 6773 6774 PetscFunctionBegin; 6775 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6776 PetscValidType(mat, 1); 6777 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6778 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6779 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6780 MatCheckPreallocated(mat, 1); 6781 6782 PetscCall(ISGetLocalSize(is, &numRows)); 6783 PetscCall(ISGetIndices(is, &rows)); 6784 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6785 PetscCall(ISRestoreIndices(is, &rows)); 6786 PetscFunctionReturn(PETSC_SUCCESS); 6787 } 6788 6789 /*@ 6790 MatGetSize - Returns the numbers of rows and columns in a matrix. 6791 6792 Not Collective 6793 6794 Input Parameter: 6795 . mat - the matrix 6796 6797 Output Parameters: 6798 + m - the number of global rows 6799 - n - the number of global columns 6800 6801 Level: beginner 6802 6803 Note: 6804 Both output parameters can be `NULL` on input. 6805 6806 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6807 @*/ 6808 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6809 { 6810 PetscFunctionBegin; 6811 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6812 if (m) *m = mat->rmap->N; 6813 if (n) *n = mat->cmap->N; 6814 PetscFunctionReturn(PETSC_SUCCESS); 6815 } 6816 6817 /*@ 6818 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6819 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6820 6821 Not Collective 6822 6823 Input Parameter: 6824 . mat - the matrix 6825 6826 Output Parameters: 6827 + m - the number of local rows, use `NULL` to not obtain this value 6828 - n - the number of local columns, use `NULL` to not obtain this value 6829 6830 Level: beginner 6831 6832 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6833 @*/ 6834 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6835 { 6836 PetscFunctionBegin; 6837 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6838 if (m) PetscAssertPointer(m, 2); 6839 if (n) PetscAssertPointer(n, 3); 6840 if (m) *m = mat->rmap->n; 6841 if (n) *n = mat->cmap->n; 6842 PetscFunctionReturn(PETSC_SUCCESS); 6843 } 6844 6845 /*@ 6846 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6847 vector one multiplies this matrix by that are owned by this processor. 6848 6849 Not Collective, unless matrix has not been allocated, then collective 6850 6851 Input Parameter: 6852 . mat - the matrix 6853 6854 Output Parameters: 6855 + m - the global index of the first local column, use `NULL` to not obtain this value 6856 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6857 6858 Level: developer 6859 6860 Notes: 6861 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6862 6863 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6864 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6865 6866 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6867 the local values in the matrix. 6868 6869 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6870 Layouts](sec_matlayout) for details on matrix layouts. 6871 6872 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6873 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6874 @*/ 6875 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6876 { 6877 PetscFunctionBegin; 6878 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6879 PetscValidType(mat, 1); 6880 if (m) PetscAssertPointer(m, 2); 6881 if (n) PetscAssertPointer(n, 3); 6882 MatCheckPreallocated(mat, 1); 6883 if (m) *m = mat->cmap->rstart; 6884 if (n) *n = mat->cmap->rend; 6885 PetscFunctionReturn(PETSC_SUCCESS); 6886 } 6887 6888 /*@ 6889 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6890 this MPI process. 6891 6892 Not Collective 6893 6894 Input Parameter: 6895 . mat - the matrix 6896 6897 Output Parameters: 6898 + m - the global index of the first local row, use `NULL` to not obtain this value 6899 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6900 6901 Level: beginner 6902 6903 Notes: 6904 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6905 6906 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6907 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6908 6909 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6910 the local values in the matrix. 6911 6912 The high argument is one more than the last element stored locally. 6913 6914 For all matrices it returns the range of matrix rows associated with rows of a vector that 6915 would contain the result of a matrix vector product with this matrix. See [Matrix 6916 Layouts](sec_matlayout) for details on matrix layouts. 6917 6918 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6919 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6920 @*/ 6921 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6922 { 6923 PetscFunctionBegin; 6924 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6925 PetscValidType(mat, 1); 6926 if (m) PetscAssertPointer(m, 2); 6927 if (n) PetscAssertPointer(n, 3); 6928 MatCheckPreallocated(mat, 1); 6929 if (m) *m = mat->rmap->rstart; 6930 if (n) *n = mat->rmap->rend; 6931 PetscFunctionReturn(PETSC_SUCCESS); 6932 } 6933 6934 /*@C 6935 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6936 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6937 6938 Not Collective, unless matrix has not been allocated 6939 6940 Input Parameter: 6941 . mat - the matrix 6942 6943 Output Parameter: 6944 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6945 where `size` is the number of MPI processes used by `mat` 6946 6947 Level: beginner 6948 6949 Notes: 6950 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6951 6952 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6953 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6954 6955 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6956 the local values in the matrix. 6957 6958 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6959 would contain the result of a matrix vector product with this matrix. See [Matrix 6960 Layouts](sec_matlayout) for details on matrix layouts. 6961 6962 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6963 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6964 `DMDAGetGhostCorners()`, `DM` 6965 @*/ 6966 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6967 { 6968 PetscFunctionBegin; 6969 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6970 PetscValidType(mat, 1); 6971 MatCheckPreallocated(mat, 1); 6972 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6973 PetscFunctionReturn(PETSC_SUCCESS); 6974 } 6975 6976 /*@C 6977 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6978 vector one multiplies this vector by that are owned by each processor. 6979 6980 Not Collective, unless matrix has not been allocated 6981 6982 Input Parameter: 6983 . mat - the matrix 6984 6985 Output Parameter: 6986 . ranges - start of each processors portion plus one more than the total length at the end 6987 6988 Level: beginner 6989 6990 Notes: 6991 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6992 6993 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6994 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6995 6996 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6997 the local values in the matrix. 6998 6999 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7000 Layouts](sec_matlayout) for details on matrix layouts. 7001 7002 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7003 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7004 `DMDAGetGhostCorners()`, `DM` 7005 @*/ 7006 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7007 { 7008 PetscFunctionBegin; 7009 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7010 PetscValidType(mat, 1); 7011 MatCheckPreallocated(mat, 1); 7012 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7013 PetscFunctionReturn(PETSC_SUCCESS); 7014 } 7015 7016 /*@ 7017 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7018 7019 Not Collective 7020 7021 Input Parameter: 7022 . A - matrix 7023 7024 Output Parameters: 7025 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7026 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7027 7028 Level: intermediate 7029 7030 Note: 7031 You should call `ISDestroy()` on the returned `IS` 7032 7033 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7034 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7035 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7036 details on matrix layouts. 7037 7038 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7039 @*/ 7040 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7041 { 7042 PetscErrorCode (*f)(Mat, IS *, IS *); 7043 7044 PetscFunctionBegin; 7045 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7046 PetscValidType(A, 1); 7047 MatCheckPreallocated(A, 1); 7048 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7049 if (f) { 7050 PetscCall((*f)(A, rows, cols)); 7051 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7052 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7053 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7054 } 7055 PetscFunctionReturn(PETSC_SUCCESS); 7056 } 7057 7058 /*@ 7059 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7060 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7061 to complete the factorization. 7062 7063 Collective 7064 7065 Input Parameters: 7066 + fact - the factorized matrix obtained with `MatGetFactor()` 7067 . mat - the matrix 7068 . row - row permutation 7069 . col - column permutation 7070 - info - structure containing 7071 .vb 7072 levels - number of levels of fill. 7073 expected fill - as ratio of original fill. 7074 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7075 missing diagonal entries) 7076 .ve 7077 7078 Level: developer 7079 7080 Notes: 7081 See [Matrix Factorization](sec_matfactor) for additional information. 7082 7083 Most users should employ the `KSP` interface for linear solvers 7084 instead of working directly with matrix algebra routines such as this. 7085 See, e.g., `KSPCreate()`. 7086 7087 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7088 7089 Fortran Note: 7090 A valid (non-null) `info` argument must be provided 7091 7092 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7093 `MatGetOrdering()`, `MatFactorInfo` 7094 @*/ 7095 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7096 { 7097 PetscFunctionBegin; 7098 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7099 PetscValidType(mat, 2); 7100 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7101 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7102 PetscAssertPointer(info, 5); 7103 PetscAssertPointer(fact, 1); 7104 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7105 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7106 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7107 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7108 MatCheckPreallocated(mat, 2); 7109 7110 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7111 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7112 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7113 PetscFunctionReturn(PETSC_SUCCESS); 7114 } 7115 7116 /*@ 7117 MatICCFactorSymbolic - Performs symbolic incomplete 7118 Cholesky factorization for a symmetric matrix. Use 7119 `MatCholeskyFactorNumeric()` to complete the factorization. 7120 7121 Collective 7122 7123 Input Parameters: 7124 + fact - the factorized matrix obtained with `MatGetFactor()` 7125 . mat - the matrix to be factored 7126 . perm - row and column permutation 7127 - info - structure containing 7128 .vb 7129 levels - number of levels of fill. 7130 expected fill - as ratio of original fill. 7131 .ve 7132 7133 Level: developer 7134 7135 Notes: 7136 Most users should employ the `KSP` interface for linear solvers 7137 instead of working directly with matrix algebra routines such as this. 7138 See, e.g., `KSPCreate()`. 7139 7140 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7141 7142 Fortran Note: 7143 A valid (non-null) `info` argument must be provided 7144 7145 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7146 @*/ 7147 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7148 { 7149 PetscFunctionBegin; 7150 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7151 PetscValidType(mat, 2); 7152 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7153 PetscAssertPointer(info, 4); 7154 PetscAssertPointer(fact, 1); 7155 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7156 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7157 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7158 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7159 MatCheckPreallocated(mat, 2); 7160 7161 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7162 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7163 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7164 PetscFunctionReturn(PETSC_SUCCESS); 7165 } 7166 7167 /*@C 7168 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7169 points to an array of valid matrices, they may be reused to store the new 7170 submatrices. 7171 7172 Collective 7173 7174 Input Parameters: 7175 + mat - the matrix 7176 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7177 . irow - index set of rows to extract 7178 . icol - index set of columns to extract 7179 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7180 7181 Output Parameter: 7182 . submat - the array of submatrices 7183 7184 Level: advanced 7185 7186 Notes: 7187 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7188 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7189 to extract a parallel submatrix. 7190 7191 Some matrix types place restrictions on the row and column 7192 indices, such as that they be sorted or that they be equal to each other. 7193 7194 The index sets may not have duplicate entries. 7195 7196 When extracting submatrices from a parallel matrix, each processor can 7197 form a different submatrix by setting the rows and columns of its 7198 individual index sets according to the local submatrix desired. 7199 7200 When finished using the submatrices, the user should destroy 7201 them with `MatDestroySubMatrices()`. 7202 7203 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7204 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7205 7206 This routine creates the matrices in submat; you should NOT create them before 7207 calling it. It also allocates the array of matrix pointers submat. 7208 7209 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7210 request one row/column in a block, they must request all rows/columns that are in 7211 that block. For example, if the block size is 2 you cannot request just row 0 and 7212 column 0. 7213 7214 Fortran Note: 7215 .vb 7216 Mat, pointer :: submat(:) 7217 .ve 7218 7219 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7220 @*/ 7221 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7222 { 7223 PetscInt i; 7224 PetscBool eq; 7225 7226 PetscFunctionBegin; 7227 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7228 PetscValidType(mat, 1); 7229 if (n) { 7230 PetscAssertPointer(irow, 3); 7231 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7232 PetscAssertPointer(icol, 4); 7233 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7234 } 7235 PetscAssertPointer(submat, 6); 7236 if (n && scall == MAT_REUSE_MATRIX) { 7237 PetscAssertPointer(*submat, 6); 7238 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7239 } 7240 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7241 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7242 MatCheckPreallocated(mat, 1); 7243 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7244 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7245 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7246 for (i = 0; i < n; i++) { 7247 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7248 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7249 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7250 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7251 if (mat->boundtocpu && mat->bindingpropagates) { 7252 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7253 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7254 } 7255 #endif 7256 } 7257 PetscFunctionReturn(PETSC_SUCCESS); 7258 } 7259 7260 /*@C 7261 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7262 7263 Collective 7264 7265 Input Parameters: 7266 + mat - the matrix 7267 . n - the number of submatrixes to be extracted 7268 . irow - index set of rows to extract 7269 . icol - index set of columns to extract 7270 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7271 7272 Output Parameter: 7273 . submat - the array of submatrices 7274 7275 Level: advanced 7276 7277 Note: 7278 This is used by `PCGASM` 7279 7280 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7281 @*/ 7282 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7283 { 7284 PetscInt i; 7285 PetscBool eq; 7286 7287 PetscFunctionBegin; 7288 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7289 PetscValidType(mat, 1); 7290 if (n) { 7291 PetscAssertPointer(irow, 3); 7292 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7293 PetscAssertPointer(icol, 4); 7294 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7295 } 7296 PetscAssertPointer(submat, 6); 7297 if (n && scall == MAT_REUSE_MATRIX) { 7298 PetscAssertPointer(*submat, 6); 7299 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7300 } 7301 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7302 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7303 MatCheckPreallocated(mat, 1); 7304 7305 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7306 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7307 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7308 for (i = 0; i < n; i++) { 7309 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7310 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7311 } 7312 PetscFunctionReturn(PETSC_SUCCESS); 7313 } 7314 7315 /*@C 7316 MatDestroyMatrices - Destroys an array of matrices 7317 7318 Collective 7319 7320 Input Parameters: 7321 + n - the number of local matrices 7322 - mat - the matrices (this is a pointer to the array of matrices) 7323 7324 Level: advanced 7325 7326 Notes: 7327 Frees not only the matrices, but also the array that contains the matrices 7328 7329 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7330 7331 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7332 @*/ 7333 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7334 { 7335 PetscInt i; 7336 7337 PetscFunctionBegin; 7338 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7339 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7340 PetscAssertPointer(mat, 2); 7341 7342 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7343 7344 /* memory is allocated even if n = 0 */ 7345 PetscCall(PetscFree(*mat)); 7346 PetscFunctionReturn(PETSC_SUCCESS); 7347 } 7348 7349 /*@C 7350 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7351 7352 Collective 7353 7354 Input Parameters: 7355 + n - the number of local matrices 7356 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7357 7358 Level: advanced 7359 7360 Note: 7361 Frees not only the matrices, but also the array that contains the matrices 7362 7363 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7364 @*/ 7365 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7366 { 7367 Mat mat0; 7368 7369 PetscFunctionBegin; 7370 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7371 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7372 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7373 PetscAssertPointer(mat, 2); 7374 7375 mat0 = (*mat)[0]; 7376 if (mat0 && mat0->ops->destroysubmatrices) { 7377 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7378 } else { 7379 PetscCall(MatDestroyMatrices(n, mat)); 7380 } 7381 PetscFunctionReturn(PETSC_SUCCESS); 7382 } 7383 7384 /*@ 7385 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7386 7387 Collective 7388 7389 Input Parameter: 7390 . mat - the matrix 7391 7392 Output Parameter: 7393 . matstruct - the sequential matrix with the nonzero structure of `mat` 7394 7395 Level: developer 7396 7397 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7398 @*/ 7399 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7400 { 7401 PetscFunctionBegin; 7402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7403 PetscAssertPointer(matstruct, 2); 7404 7405 PetscValidType(mat, 1); 7406 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7407 MatCheckPreallocated(mat, 1); 7408 7409 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7410 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7411 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7412 PetscFunctionReturn(PETSC_SUCCESS); 7413 } 7414 7415 /*@C 7416 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7417 7418 Collective 7419 7420 Input Parameter: 7421 . mat - the matrix 7422 7423 Level: advanced 7424 7425 Note: 7426 This is not needed, one can just call `MatDestroy()` 7427 7428 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7429 @*/ 7430 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7431 { 7432 PetscFunctionBegin; 7433 PetscAssertPointer(mat, 1); 7434 PetscCall(MatDestroy(mat)); 7435 PetscFunctionReturn(PETSC_SUCCESS); 7436 } 7437 7438 /*@ 7439 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7440 replaces the index sets by larger ones that represent submatrices with 7441 additional overlap. 7442 7443 Collective 7444 7445 Input Parameters: 7446 + mat - the matrix 7447 . n - the number of index sets 7448 . is - the array of index sets (these index sets will changed during the call) 7449 - ov - the additional overlap requested 7450 7451 Options Database Key: 7452 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7453 7454 Level: developer 7455 7456 Note: 7457 The computed overlap preserves the matrix block sizes when the blocks are square. 7458 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7459 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7460 7461 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7462 @*/ 7463 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7464 { 7465 PetscInt i, bs, cbs; 7466 7467 PetscFunctionBegin; 7468 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7469 PetscValidType(mat, 1); 7470 PetscValidLogicalCollectiveInt(mat, n, 2); 7471 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7472 if (n) { 7473 PetscAssertPointer(is, 3); 7474 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7475 } 7476 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7477 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7478 MatCheckPreallocated(mat, 1); 7479 7480 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7481 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7482 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7483 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7484 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7485 if (bs == cbs) { 7486 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7487 } 7488 PetscFunctionReturn(PETSC_SUCCESS); 7489 } 7490 7491 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7492 7493 /*@ 7494 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7495 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7496 additional overlap. 7497 7498 Collective 7499 7500 Input Parameters: 7501 + mat - the matrix 7502 . n - the number of index sets 7503 . is - the array of index sets (these index sets will changed during the call) 7504 - ov - the additional overlap requested 7505 7506 ` Options Database Key: 7507 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7508 7509 Level: developer 7510 7511 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7512 @*/ 7513 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7514 { 7515 PetscInt i; 7516 7517 PetscFunctionBegin; 7518 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7519 PetscValidType(mat, 1); 7520 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7521 if (n) { 7522 PetscAssertPointer(is, 3); 7523 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7524 } 7525 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7526 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7527 MatCheckPreallocated(mat, 1); 7528 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7529 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7530 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7531 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7532 PetscFunctionReturn(PETSC_SUCCESS); 7533 } 7534 7535 /*@ 7536 MatGetBlockSize - Returns the matrix block size. 7537 7538 Not Collective 7539 7540 Input Parameter: 7541 . mat - the matrix 7542 7543 Output Parameter: 7544 . bs - block size 7545 7546 Level: intermediate 7547 7548 Notes: 7549 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7550 7551 If the block size has not been set yet this routine returns 1. 7552 7553 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7554 @*/ 7555 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7556 { 7557 PetscFunctionBegin; 7558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7559 PetscAssertPointer(bs, 2); 7560 *bs = mat->rmap->bs; 7561 PetscFunctionReturn(PETSC_SUCCESS); 7562 } 7563 7564 /*@ 7565 MatGetBlockSizes - Returns the matrix block row and column sizes. 7566 7567 Not Collective 7568 7569 Input Parameter: 7570 . mat - the matrix 7571 7572 Output Parameters: 7573 + rbs - row block size 7574 - cbs - column block size 7575 7576 Level: intermediate 7577 7578 Notes: 7579 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7580 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7581 7582 If a block size has not been set yet this routine returns 1. 7583 7584 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7585 @*/ 7586 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7587 { 7588 PetscFunctionBegin; 7589 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7590 if (rbs) PetscAssertPointer(rbs, 2); 7591 if (cbs) PetscAssertPointer(cbs, 3); 7592 if (rbs) *rbs = mat->rmap->bs; 7593 if (cbs) *cbs = mat->cmap->bs; 7594 PetscFunctionReturn(PETSC_SUCCESS); 7595 } 7596 7597 /*@ 7598 MatSetBlockSize - Sets the matrix block size. 7599 7600 Logically Collective 7601 7602 Input Parameters: 7603 + mat - the matrix 7604 - bs - block size 7605 7606 Level: intermediate 7607 7608 Notes: 7609 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7610 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7611 7612 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7613 is compatible with the matrix local sizes. 7614 7615 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7616 @*/ 7617 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7618 { 7619 PetscFunctionBegin; 7620 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7621 PetscValidLogicalCollectiveInt(mat, bs, 2); 7622 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7623 PetscFunctionReturn(PETSC_SUCCESS); 7624 } 7625 7626 typedef struct { 7627 PetscInt n; 7628 IS *is; 7629 Mat *mat; 7630 PetscObjectState nonzerostate; 7631 Mat C; 7632 } EnvelopeData; 7633 7634 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7635 { 7636 EnvelopeData *edata = (EnvelopeData *)*ptr; 7637 7638 PetscFunctionBegin; 7639 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7640 PetscCall(PetscFree(edata->is)); 7641 PetscCall(PetscFree(edata)); 7642 PetscFunctionReturn(PETSC_SUCCESS); 7643 } 7644 7645 /*@ 7646 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7647 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7648 7649 Collective 7650 7651 Input Parameter: 7652 . mat - the matrix 7653 7654 Level: intermediate 7655 7656 Notes: 7657 There can be zeros within the blocks 7658 7659 The blocks can overlap between processes, including laying on more than two processes 7660 7661 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7662 @*/ 7663 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7664 { 7665 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7666 PetscInt *diag, *odiag, sc; 7667 VecScatter scatter; 7668 PetscScalar *seqv; 7669 const PetscScalar *parv; 7670 const PetscInt *ia, *ja; 7671 PetscBool set, flag, done; 7672 Mat AA = mat, A; 7673 MPI_Comm comm; 7674 PetscMPIInt rank, size, tag; 7675 MPI_Status status; 7676 PetscContainer container; 7677 EnvelopeData *edata; 7678 Vec seq, par; 7679 IS isglobal; 7680 7681 PetscFunctionBegin; 7682 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7683 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7684 if (!set || !flag) { 7685 /* TODO: only needs nonzero structure of transpose */ 7686 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7687 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7688 } 7689 PetscCall(MatAIJGetLocalMat(AA, &A)); 7690 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7691 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7692 7693 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7694 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7695 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7696 PetscCallMPI(MPI_Comm_size(comm, &size)); 7697 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7698 7699 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7700 7701 if (rank > 0) { 7702 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7703 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7704 } 7705 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7706 for (i = 0; i < n; i++) { 7707 env = PetscMax(env, ja[ia[i + 1] - 1]); 7708 II = rstart + i; 7709 if (env == II) { 7710 starts[lblocks] = tbs; 7711 sizes[lblocks++] = 1 + II - tbs; 7712 tbs = 1 + II; 7713 } 7714 } 7715 if (rank < size - 1) { 7716 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7717 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7718 } 7719 7720 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7721 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7722 PetscCall(MatDestroy(&A)); 7723 7724 PetscCall(PetscNew(&edata)); 7725 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7726 edata->n = lblocks; 7727 /* create IS needed for extracting blocks from the original matrix */ 7728 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7729 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7730 7731 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7732 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7733 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7734 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7735 PetscCall(MatSetType(edata->C, MATAIJ)); 7736 7737 /* Communicate the start and end of each row, from each block to the correct rank */ 7738 /* TODO: Use PetscSF instead of VecScatter */ 7739 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7740 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7741 PetscCall(VecGetArrayWrite(seq, &seqv)); 7742 for (PetscInt i = 0; i < lblocks; i++) { 7743 for (PetscInt j = 0; j < sizes[i]; j++) { 7744 seqv[cnt] = starts[i]; 7745 seqv[cnt + 1] = starts[i] + sizes[i]; 7746 cnt += 2; 7747 } 7748 } 7749 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7750 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7751 sc -= cnt; 7752 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7753 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7754 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7755 PetscCall(ISDestroy(&isglobal)); 7756 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7757 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7758 PetscCall(VecScatterDestroy(&scatter)); 7759 PetscCall(VecDestroy(&seq)); 7760 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7761 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7762 PetscCall(VecGetArrayRead(par, &parv)); 7763 cnt = 0; 7764 PetscCall(MatGetSize(mat, NULL, &n)); 7765 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7766 PetscInt start, end, d = 0, od = 0; 7767 7768 start = (PetscInt)PetscRealPart(parv[cnt]); 7769 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7770 cnt += 2; 7771 7772 if (start < cstart) { 7773 od += cstart - start + n - cend; 7774 d += cend - cstart; 7775 } else if (start < cend) { 7776 od += n - cend; 7777 d += cend - start; 7778 } else od += n - start; 7779 if (end <= cstart) { 7780 od -= cstart - end + n - cend; 7781 d -= cend - cstart; 7782 } else if (end < cend) { 7783 od -= n - cend; 7784 d -= cend - end; 7785 } else od -= n - end; 7786 7787 odiag[i] = od; 7788 diag[i] = d; 7789 } 7790 PetscCall(VecRestoreArrayRead(par, &parv)); 7791 PetscCall(VecDestroy(&par)); 7792 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7793 PetscCall(PetscFree2(diag, odiag)); 7794 PetscCall(PetscFree2(sizes, starts)); 7795 7796 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7797 PetscCall(PetscContainerSetPointer(container, edata)); 7798 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7799 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7800 PetscCall(PetscObjectDereference((PetscObject)container)); 7801 PetscFunctionReturn(PETSC_SUCCESS); 7802 } 7803 7804 /*@ 7805 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7806 7807 Collective 7808 7809 Input Parameters: 7810 + A - the matrix 7811 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7812 7813 Output Parameter: 7814 . C - matrix with inverted block diagonal of `A` 7815 7816 Level: advanced 7817 7818 Note: 7819 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7820 7821 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7822 @*/ 7823 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7824 { 7825 PetscContainer container; 7826 EnvelopeData *edata; 7827 PetscObjectState nonzerostate; 7828 7829 PetscFunctionBegin; 7830 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7831 if (!container) { 7832 PetscCall(MatComputeVariableBlockEnvelope(A)); 7833 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7834 } 7835 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7836 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7837 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7838 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7839 7840 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7841 *C = edata->C; 7842 7843 for (PetscInt i = 0; i < edata->n; i++) { 7844 Mat D; 7845 PetscScalar *dvalues; 7846 7847 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7848 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7849 PetscCall(MatSeqDenseInvert(D)); 7850 PetscCall(MatDenseGetArray(D, &dvalues)); 7851 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7852 PetscCall(MatDestroy(&D)); 7853 } 7854 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7855 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7856 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7857 PetscFunctionReturn(PETSC_SUCCESS); 7858 } 7859 7860 /*@ 7861 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7862 7863 Not Collective 7864 7865 Input Parameters: 7866 + mat - the matrix 7867 . nblocks - the number of blocks on this process, each block can only exist on a single process 7868 - bsizes - the block sizes 7869 7870 Level: intermediate 7871 7872 Notes: 7873 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7874 7875 Each variable point-block set of degrees of freedom must live on a single MPI process. That is a point block cannot straddle two MPI processes. 7876 7877 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7878 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7879 @*/ 7880 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7881 { 7882 PetscInt ncnt = 0, nlocal; 7883 7884 PetscFunctionBegin; 7885 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7886 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7887 PetscCheck(nblocks >= 0 && nblocks <= nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks %" PetscInt_FMT " is not in [0, %" PetscInt_FMT "]", nblocks, nlocal); 7888 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7889 PetscCheck(ncnt == nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local block sizes %" PetscInt_FMT " does not equal local size of matrix %" PetscInt_FMT, ncnt, nlocal); 7890 PetscCall(PetscFree(mat->bsizes)); 7891 mat->nblocks = nblocks; 7892 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7893 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7894 PetscFunctionReturn(PETSC_SUCCESS); 7895 } 7896 7897 /*@C 7898 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7899 7900 Not Collective; No Fortran Support 7901 7902 Input Parameter: 7903 . mat - the matrix 7904 7905 Output Parameters: 7906 + nblocks - the number of blocks on this process 7907 - bsizes - the block sizes 7908 7909 Level: intermediate 7910 7911 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7912 @*/ 7913 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7914 { 7915 PetscFunctionBegin; 7916 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7917 if (nblocks) *nblocks = mat->nblocks; 7918 if (bsizes) *bsizes = mat->bsizes; 7919 PetscFunctionReturn(PETSC_SUCCESS); 7920 } 7921 7922 /* 7923 MatSelectVariableBlockSizes - When creating a submatrix, pass on the variable block sizes 7924 7925 Not Collective 7926 7927 Input Parameter: 7928 + subA - the submatrix 7929 . A - the original matrix 7930 - isrow - The `IS` of selected rows for the submatrix 7931 7932 Level: developer 7933 7934 .seealso: [](ch_matrices), `Mat`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7935 */ 7936 static PetscErrorCode MatSelectVariableBlockSizes(Mat subA, Mat A, IS isrow) 7937 { 7938 const PetscInt *rows; 7939 PetscInt n, rStart, rEnd, Nb = 0; 7940 7941 PetscFunctionBegin; 7942 if (!A->bsizes) PetscFunctionReturn(PETSC_SUCCESS); 7943 // The IS contains global row numbers, we cannot preserve blocks if it contains off-process entries 7944 PetscCall(MatGetOwnershipRange(A, &rStart, &rEnd)); 7945 PetscCall(ISGetIndices(isrow, &rows)); 7946 PetscCall(ISGetLocalSize(isrow, &n)); 7947 for (PetscInt i = 0; i < n; ++i) { 7948 if (rows[i] < rStart || rows[i] >= rEnd) { 7949 PetscCall(ISRestoreIndices(isrow, &rows)); 7950 PetscFunctionReturn(PETSC_SUCCESS); 7951 } 7952 } 7953 for (PetscInt b = 0, gr = rStart, i = 0; b < A->nblocks; ++b) { 7954 PetscBool occupied = PETSC_FALSE; 7955 7956 for (PetscInt br = 0; br < A->bsizes[b]; ++br) { 7957 const PetscInt row = gr + br; 7958 7959 if (i == n) break; 7960 if (rows[i] == row) { 7961 occupied = PETSC_TRUE; 7962 ++i; 7963 } 7964 while (i < n && rows[i] < row) ++i; 7965 } 7966 gr += A->bsizes[b]; 7967 if (occupied) ++Nb; 7968 } 7969 subA->nblocks = Nb; 7970 PetscCall(PetscFree(subA->bsizes)); 7971 PetscCall(PetscMalloc1(subA->nblocks, &subA->bsizes)); 7972 PetscInt sb = 0; 7973 for (PetscInt b = 0, gr = rStart, i = 0; b < A->nblocks; ++b) { 7974 if (sb < subA->nblocks) subA->bsizes[sb] = 0; 7975 for (PetscInt br = 0; br < A->bsizes[b]; ++br) { 7976 const PetscInt row = gr + br; 7977 7978 if (i == n) break; 7979 if (rows[i] == row) { 7980 ++subA->bsizes[sb]; 7981 ++i; 7982 } 7983 while (i < n && rows[i] < row) ++i; 7984 } 7985 gr += A->bsizes[b]; 7986 if (sb < subA->nblocks && subA->bsizes[sb]) ++sb; 7987 } 7988 PetscCheck(sb == subA->nblocks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of blocks %" PetscInt_FMT " != %" PetscInt_FMT, sb, subA->nblocks); 7989 PetscInt nlocal, ncnt = 0; 7990 PetscCall(MatGetLocalSize(subA, &nlocal, NULL)); 7991 PetscCheck(subA->nblocks >= 0 && subA->nblocks <= nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks %" PetscInt_FMT " is not in [0, %" PetscInt_FMT "]", subA->nblocks, nlocal); 7992 for (PetscInt i = 0; i < subA->nblocks; i++) ncnt += subA->bsizes[i]; 7993 PetscCheck(ncnt == nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local block sizes %" PetscInt_FMT " does not equal local size of matrix %" PetscInt_FMT, ncnt, nlocal); 7994 PetscCall(ISRestoreIndices(isrow, &rows)); 7995 PetscFunctionReturn(PETSC_SUCCESS); 7996 } 7997 7998 /*@ 7999 MatSetBlockSizes - Sets the matrix block row and column sizes. 8000 8001 Logically Collective 8002 8003 Input Parameters: 8004 + mat - the matrix 8005 . rbs - row block size 8006 - cbs - column block size 8007 8008 Level: intermediate 8009 8010 Notes: 8011 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 8012 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 8013 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 8014 8015 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 8016 are compatible with the matrix local sizes. 8017 8018 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 8019 8020 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 8021 @*/ 8022 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 8023 { 8024 PetscFunctionBegin; 8025 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8026 PetscValidLogicalCollectiveInt(mat, rbs, 2); 8027 PetscValidLogicalCollectiveInt(mat, cbs, 3); 8028 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 8029 if (mat->rmap->refcnt) { 8030 ISLocalToGlobalMapping l2g = NULL; 8031 PetscLayout nmap = NULL; 8032 8033 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 8034 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 8035 PetscCall(PetscLayoutDestroy(&mat->rmap)); 8036 mat->rmap = nmap; 8037 mat->rmap->mapping = l2g; 8038 } 8039 if (mat->cmap->refcnt) { 8040 ISLocalToGlobalMapping l2g = NULL; 8041 PetscLayout nmap = NULL; 8042 8043 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 8044 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 8045 PetscCall(PetscLayoutDestroy(&mat->cmap)); 8046 mat->cmap = nmap; 8047 mat->cmap->mapping = l2g; 8048 } 8049 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 8050 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 8051 PetscFunctionReturn(PETSC_SUCCESS); 8052 } 8053 8054 /*@ 8055 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 8056 8057 Logically Collective 8058 8059 Input Parameters: 8060 + mat - the matrix 8061 . fromRow - matrix from which to copy row block size 8062 - fromCol - matrix from which to copy column block size (can be same as fromRow) 8063 8064 Level: developer 8065 8066 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8067 @*/ 8068 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8069 { 8070 PetscFunctionBegin; 8071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8072 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8073 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8074 PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8075 PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8076 PetscFunctionReturn(PETSC_SUCCESS); 8077 } 8078 8079 /*@ 8080 MatResidual - Default routine to calculate the residual r = b - Ax 8081 8082 Collective 8083 8084 Input Parameters: 8085 + mat - the matrix 8086 . b - the right-hand-side 8087 - x - the approximate solution 8088 8089 Output Parameter: 8090 . r - location to store the residual 8091 8092 Level: developer 8093 8094 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8095 @*/ 8096 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8097 { 8098 PetscFunctionBegin; 8099 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8100 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8101 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8102 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8103 PetscValidType(mat, 1); 8104 MatCheckPreallocated(mat, 1); 8105 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8106 if (!mat->ops->residual) { 8107 PetscCall(MatMult(mat, x, r)); 8108 PetscCall(VecAYPX(r, -1.0, b)); 8109 } else { 8110 PetscUseTypeMethod(mat, residual, b, x, r); 8111 } 8112 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8113 PetscFunctionReturn(PETSC_SUCCESS); 8114 } 8115 8116 /*@C 8117 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8118 8119 Collective 8120 8121 Input Parameters: 8122 + mat - the matrix 8123 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8124 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8125 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8126 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8127 always used. 8128 8129 Output Parameters: 8130 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8131 . 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 8132 . ja - the column indices, use `NULL` if not needed 8133 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8134 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8135 8136 Level: developer 8137 8138 Notes: 8139 You CANNOT change any of the ia[] or ja[] values. 8140 8141 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8142 8143 Fortran Notes: 8144 Use 8145 .vb 8146 PetscInt, pointer :: ia(:),ja(:) 8147 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8148 ! Access the ith and jth entries via ia(i) and ja(j) 8149 .ve 8150 8151 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8152 @*/ 8153 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8154 { 8155 PetscFunctionBegin; 8156 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8157 PetscValidType(mat, 1); 8158 if (n) PetscAssertPointer(n, 5); 8159 if (ia) PetscAssertPointer(ia, 6); 8160 if (ja) PetscAssertPointer(ja, 7); 8161 if (done) PetscAssertPointer(done, 8); 8162 MatCheckPreallocated(mat, 1); 8163 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8164 else { 8165 if (done) *done = PETSC_TRUE; 8166 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8167 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8168 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8169 } 8170 PetscFunctionReturn(PETSC_SUCCESS); 8171 } 8172 8173 /*@C 8174 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8175 8176 Collective 8177 8178 Input Parameters: 8179 + mat - the matrix 8180 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8181 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8182 symmetrized 8183 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8184 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8185 always used. 8186 . n - number of columns in the (possibly compressed) matrix 8187 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8188 - ja - the row indices 8189 8190 Output Parameter: 8191 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8192 8193 Level: developer 8194 8195 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8196 @*/ 8197 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8198 { 8199 PetscFunctionBegin; 8200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8201 PetscValidType(mat, 1); 8202 PetscAssertPointer(n, 5); 8203 if (ia) PetscAssertPointer(ia, 6); 8204 if (ja) PetscAssertPointer(ja, 7); 8205 PetscAssertPointer(done, 8); 8206 MatCheckPreallocated(mat, 1); 8207 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8208 else { 8209 *done = PETSC_TRUE; 8210 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8211 } 8212 PetscFunctionReturn(PETSC_SUCCESS); 8213 } 8214 8215 /*@C 8216 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8217 8218 Collective 8219 8220 Input Parameters: 8221 + mat - the matrix 8222 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8223 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8224 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8225 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8226 always used. 8227 . n - size of (possibly compressed) matrix 8228 . ia - the row pointers 8229 - ja - the column indices 8230 8231 Output Parameter: 8232 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8233 8234 Level: developer 8235 8236 Note: 8237 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8238 us of the array after it has been restored. If you pass `NULL`, it will 8239 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8240 8241 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8242 @*/ 8243 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8244 { 8245 PetscFunctionBegin; 8246 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8247 PetscValidType(mat, 1); 8248 if (ia) PetscAssertPointer(ia, 6); 8249 if (ja) PetscAssertPointer(ja, 7); 8250 if (done) PetscAssertPointer(done, 8); 8251 MatCheckPreallocated(mat, 1); 8252 8253 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8254 else { 8255 if (done) *done = PETSC_TRUE; 8256 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8257 if (n) *n = 0; 8258 if (ia) *ia = NULL; 8259 if (ja) *ja = NULL; 8260 } 8261 PetscFunctionReturn(PETSC_SUCCESS); 8262 } 8263 8264 /*@C 8265 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8266 8267 Collective 8268 8269 Input Parameters: 8270 + mat - the matrix 8271 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8272 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8273 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8274 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8275 always used. 8276 8277 Output Parameters: 8278 + n - size of (possibly compressed) matrix 8279 . ia - the column pointers 8280 . ja - the row indices 8281 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8282 8283 Level: developer 8284 8285 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8286 @*/ 8287 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8288 { 8289 PetscFunctionBegin; 8290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8291 PetscValidType(mat, 1); 8292 if (ia) PetscAssertPointer(ia, 6); 8293 if (ja) PetscAssertPointer(ja, 7); 8294 PetscAssertPointer(done, 8); 8295 MatCheckPreallocated(mat, 1); 8296 8297 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8298 else { 8299 *done = PETSC_TRUE; 8300 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8301 if (n) *n = 0; 8302 if (ia) *ia = NULL; 8303 if (ja) *ja = NULL; 8304 } 8305 PetscFunctionReturn(PETSC_SUCCESS); 8306 } 8307 8308 /*@ 8309 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8310 `MatGetColumnIJ()`. 8311 8312 Collective 8313 8314 Input Parameters: 8315 + mat - the matrix 8316 . ncolors - maximum color value 8317 . n - number of entries in colorarray 8318 - colorarray - array indicating color for each column 8319 8320 Output Parameter: 8321 . iscoloring - coloring generated using colorarray information 8322 8323 Level: developer 8324 8325 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8326 @*/ 8327 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8328 { 8329 PetscFunctionBegin; 8330 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8331 PetscValidType(mat, 1); 8332 PetscAssertPointer(colorarray, 4); 8333 PetscAssertPointer(iscoloring, 5); 8334 MatCheckPreallocated(mat, 1); 8335 8336 if (!mat->ops->coloringpatch) { 8337 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8338 } else { 8339 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8340 } 8341 PetscFunctionReturn(PETSC_SUCCESS); 8342 } 8343 8344 /*@ 8345 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8346 8347 Logically Collective 8348 8349 Input Parameter: 8350 . mat - the factored matrix to be reset 8351 8352 Level: developer 8353 8354 Notes: 8355 This routine should be used only with factored matrices formed by in-place 8356 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8357 format). This option can save memory, for example, when solving nonlinear 8358 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8359 ILU(0) preconditioner. 8360 8361 One can specify in-place ILU(0) factorization by calling 8362 .vb 8363 PCType(pc,PCILU); 8364 PCFactorSeUseInPlace(pc); 8365 .ve 8366 or by using the options -pc_type ilu -pc_factor_in_place 8367 8368 In-place factorization ILU(0) can also be used as a local 8369 solver for the blocks within the block Jacobi or additive Schwarz 8370 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8371 for details on setting local solver options. 8372 8373 Most users should employ the `KSP` interface for linear solvers 8374 instead of working directly with matrix algebra routines such as this. 8375 See, e.g., `KSPCreate()`. 8376 8377 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8378 @*/ 8379 PetscErrorCode MatSetUnfactored(Mat mat) 8380 { 8381 PetscFunctionBegin; 8382 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8383 PetscValidType(mat, 1); 8384 MatCheckPreallocated(mat, 1); 8385 mat->factortype = MAT_FACTOR_NONE; 8386 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8387 PetscUseTypeMethod(mat, setunfactored); 8388 PetscFunctionReturn(PETSC_SUCCESS); 8389 } 8390 8391 /*@ 8392 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8393 as the original matrix. 8394 8395 Collective 8396 8397 Input Parameters: 8398 + mat - the original matrix 8399 . isrow - parallel `IS` containing the rows this processor should obtain 8400 . 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. 8401 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8402 8403 Output Parameter: 8404 . newmat - the new submatrix, of the same type as the original matrix 8405 8406 Level: advanced 8407 8408 Notes: 8409 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8410 8411 Some matrix types place restrictions on the row and column indices, such 8412 as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block; 8413 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8414 8415 The index sets may not have duplicate entries. 8416 8417 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8418 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8419 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8420 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8421 you are finished using it. 8422 8423 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8424 the input matrix. 8425 8426 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8427 8428 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8429 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8430 8431 Example usage: 8432 Consider the following 8x8 matrix with 34 non-zero values, that is 8433 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8434 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8435 as follows 8436 .vb 8437 1 2 0 | 0 3 0 | 0 4 8438 Proc0 0 5 6 | 7 0 0 | 8 0 8439 9 0 10 | 11 0 0 | 12 0 8440 ------------------------------------- 8441 13 0 14 | 15 16 17 | 0 0 8442 Proc1 0 18 0 | 19 20 21 | 0 0 8443 0 0 0 | 22 23 0 | 24 0 8444 ------------------------------------- 8445 Proc2 25 26 27 | 0 0 28 | 29 0 8446 30 0 0 | 31 32 33 | 0 34 8447 .ve 8448 8449 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8450 8451 .vb 8452 2 0 | 0 3 0 | 0 8453 Proc0 5 6 | 7 0 0 | 8 8454 ------------------------------- 8455 Proc1 18 0 | 19 20 21 | 0 8456 ------------------------------- 8457 Proc2 26 27 | 0 0 28 | 29 8458 0 0 | 31 32 33 | 0 8459 .ve 8460 8461 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8462 @*/ 8463 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8464 { 8465 PetscMPIInt size; 8466 Mat *local; 8467 IS iscoltmp; 8468 PetscBool flg; 8469 8470 PetscFunctionBegin; 8471 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8472 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8473 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8474 PetscAssertPointer(newmat, 5); 8475 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8476 PetscValidType(mat, 1); 8477 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8478 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8479 8480 MatCheckPreallocated(mat, 1); 8481 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8482 8483 if (!iscol || isrow == iscol) { 8484 PetscBool stride; 8485 PetscMPIInt grabentirematrix = 0, grab; 8486 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8487 if (stride) { 8488 PetscInt first, step, n, rstart, rend; 8489 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8490 if (step == 1) { 8491 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8492 if (rstart == first) { 8493 PetscCall(ISGetLocalSize(isrow, &n)); 8494 if (n == rend - rstart) grabentirematrix = 1; 8495 } 8496 } 8497 } 8498 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8499 if (grab) { 8500 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8501 if (cll == MAT_INITIAL_MATRIX) { 8502 *newmat = mat; 8503 PetscCall(PetscObjectReference((PetscObject)mat)); 8504 } 8505 PetscFunctionReturn(PETSC_SUCCESS); 8506 } 8507 } 8508 8509 if (!iscol) { 8510 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8511 } else { 8512 iscoltmp = iscol; 8513 } 8514 8515 /* if original matrix is on just one processor then use submatrix generated */ 8516 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8517 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8518 goto setproperties; 8519 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8520 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8521 *newmat = *local; 8522 PetscCall(PetscFree(local)); 8523 goto setproperties; 8524 } else if (!mat->ops->createsubmatrix) { 8525 /* Create a new matrix type that implements the operation using the full matrix */ 8526 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8527 switch (cll) { 8528 case MAT_INITIAL_MATRIX: 8529 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8530 break; 8531 case MAT_REUSE_MATRIX: 8532 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8533 break; 8534 default: 8535 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8536 } 8537 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8538 goto setproperties; 8539 } 8540 8541 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8542 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8543 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8544 8545 setproperties: 8546 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8547 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8548 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8549 } 8550 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8551 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8552 if (!iscol || isrow == iscol) PetscCall(MatSelectVariableBlockSizes(*newmat, mat, isrow)); 8553 PetscFunctionReturn(PETSC_SUCCESS); 8554 } 8555 8556 /*@ 8557 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8558 8559 Not Collective 8560 8561 Input Parameters: 8562 + A - the matrix we wish to propagate options from 8563 - B - the matrix we wish to propagate options to 8564 8565 Level: beginner 8566 8567 Note: 8568 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8569 8570 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8571 @*/ 8572 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8573 { 8574 PetscFunctionBegin; 8575 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8576 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8577 B->symmetry_eternal = A->symmetry_eternal; 8578 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8579 B->symmetric = A->symmetric; 8580 B->structurally_symmetric = A->structurally_symmetric; 8581 B->spd = A->spd; 8582 B->hermitian = A->hermitian; 8583 PetscFunctionReturn(PETSC_SUCCESS); 8584 } 8585 8586 /*@ 8587 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8588 used during the assembly process to store values that belong to 8589 other processors. 8590 8591 Not Collective 8592 8593 Input Parameters: 8594 + mat - the matrix 8595 . size - the initial size of the stash. 8596 - bsize - the initial size of the block-stash(if used). 8597 8598 Options Database Keys: 8599 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8600 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8601 8602 Level: intermediate 8603 8604 Notes: 8605 The block-stash is used for values set with `MatSetValuesBlocked()` while 8606 the stash is used for values set with `MatSetValues()` 8607 8608 Run with the option -info and look for output of the form 8609 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8610 to determine the appropriate value, MM, to use for size and 8611 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8612 to determine the value, BMM to use for bsize 8613 8614 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8615 @*/ 8616 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8617 { 8618 PetscFunctionBegin; 8619 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8620 PetscValidType(mat, 1); 8621 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8622 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8623 PetscFunctionReturn(PETSC_SUCCESS); 8624 } 8625 8626 /*@ 8627 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8628 the matrix 8629 8630 Neighbor-wise Collective 8631 8632 Input Parameters: 8633 + A - the matrix 8634 . x - the vector to be multiplied by the interpolation operator 8635 - y - the vector to be added to the result 8636 8637 Output Parameter: 8638 . w - the resulting vector 8639 8640 Level: intermediate 8641 8642 Notes: 8643 `w` may be the same vector as `y`. 8644 8645 This allows one to use either the restriction or interpolation (its transpose) 8646 matrix to do the interpolation 8647 8648 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8649 @*/ 8650 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8651 { 8652 PetscInt M, N, Ny; 8653 8654 PetscFunctionBegin; 8655 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8656 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8657 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8658 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8659 PetscCall(MatGetSize(A, &M, &N)); 8660 PetscCall(VecGetSize(y, &Ny)); 8661 if (M == Ny) { 8662 PetscCall(MatMultAdd(A, x, y, w)); 8663 } else { 8664 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8665 } 8666 PetscFunctionReturn(PETSC_SUCCESS); 8667 } 8668 8669 /*@ 8670 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8671 the matrix 8672 8673 Neighbor-wise Collective 8674 8675 Input Parameters: 8676 + A - the matrix 8677 - x - the vector to be interpolated 8678 8679 Output Parameter: 8680 . y - the resulting vector 8681 8682 Level: intermediate 8683 8684 Note: 8685 This allows one to use either the restriction or interpolation (its transpose) 8686 matrix to do the interpolation 8687 8688 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8689 @*/ 8690 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8691 { 8692 PetscInt M, N, Ny; 8693 8694 PetscFunctionBegin; 8695 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8696 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8697 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8698 PetscCall(MatGetSize(A, &M, &N)); 8699 PetscCall(VecGetSize(y, &Ny)); 8700 if (M == Ny) { 8701 PetscCall(MatMult(A, x, y)); 8702 } else { 8703 PetscCall(MatMultTranspose(A, x, y)); 8704 } 8705 PetscFunctionReturn(PETSC_SUCCESS); 8706 } 8707 8708 /*@ 8709 MatRestrict - $y = A*x$ or $A^T*x$ 8710 8711 Neighbor-wise Collective 8712 8713 Input Parameters: 8714 + A - the matrix 8715 - x - the vector to be restricted 8716 8717 Output Parameter: 8718 . y - the resulting vector 8719 8720 Level: intermediate 8721 8722 Note: 8723 This allows one to use either the restriction or interpolation (its transpose) 8724 matrix to do the restriction 8725 8726 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8727 @*/ 8728 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8729 { 8730 PetscInt M, N, Nx; 8731 8732 PetscFunctionBegin; 8733 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8734 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8735 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8736 PetscCall(MatGetSize(A, &M, &N)); 8737 PetscCall(VecGetSize(x, &Nx)); 8738 if (M == Nx) { 8739 PetscCall(MatMultTranspose(A, x, y)); 8740 } else { 8741 PetscCall(MatMult(A, x, y)); 8742 } 8743 PetscFunctionReturn(PETSC_SUCCESS); 8744 } 8745 8746 /*@ 8747 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8748 8749 Neighbor-wise Collective 8750 8751 Input Parameters: 8752 + A - the matrix 8753 . x - the input dense matrix to be multiplied 8754 - w - the input dense matrix to be added to the result 8755 8756 Output Parameter: 8757 . y - the output dense matrix 8758 8759 Level: intermediate 8760 8761 Note: 8762 This allows one to use either the restriction or interpolation (its transpose) 8763 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8764 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8765 8766 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8767 @*/ 8768 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8769 { 8770 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8771 PetscBool trans = PETSC_TRUE; 8772 MatReuse reuse = MAT_INITIAL_MATRIX; 8773 8774 PetscFunctionBegin; 8775 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8776 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8777 PetscValidType(x, 2); 8778 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8779 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8780 PetscCall(MatGetSize(A, &M, &N)); 8781 PetscCall(MatGetSize(x, &Mx, &Nx)); 8782 if (N == Mx) trans = PETSC_FALSE; 8783 else PetscCheck(M == Mx, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Size mismatch: A %" PetscInt_FMT "x%" PetscInt_FMT ", X %" PetscInt_FMT "x%" PetscInt_FMT, M, N, Mx, Nx); 8784 Mo = trans ? N : M; 8785 if (*y) { 8786 PetscCall(MatGetSize(*y, &My, &Ny)); 8787 if (Mo == My && Nx == Ny) { 8788 reuse = MAT_REUSE_MATRIX; 8789 } else { 8790 PetscCheck(w || *y != w, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot reuse y and w, size mismatch: A %" PetscInt_FMT "x%" PetscInt_FMT ", X %" PetscInt_FMT "x%" PetscInt_FMT ", Y %" PetscInt_FMT "x%" PetscInt_FMT, M, N, Mx, Nx, My, Ny); 8791 PetscCall(MatDestroy(y)); 8792 } 8793 } 8794 8795 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8796 PetscBool flg; 8797 8798 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8799 if (w) { 8800 PetscInt My, Ny, Mw, Nw; 8801 8802 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8803 PetscCall(MatGetSize(*y, &My, &Ny)); 8804 PetscCall(MatGetSize(w, &Mw, &Nw)); 8805 if (!flg || My != Mw || Ny != Nw) w = NULL; 8806 } 8807 if (!w) { 8808 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8809 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8810 PetscCall(PetscObjectDereference((PetscObject)w)); 8811 } else { 8812 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8813 } 8814 } 8815 if (!trans) { 8816 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8817 } else { 8818 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8819 } 8820 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8821 PetscFunctionReturn(PETSC_SUCCESS); 8822 } 8823 8824 /*@ 8825 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8826 8827 Neighbor-wise Collective 8828 8829 Input Parameters: 8830 + A - the matrix 8831 - x - the input dense matrix 8832 8833 Output Parameter: 8834 . y - the output dense matrix 8835 8836 Level: intermediate 8837 8838 Note: 8839 This allows one to use either the restriction or interpolation (its transpose) 8840 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8841 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8842 8843 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8844 @*/ 8845 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8846 { 8847 PetscFunctionBegin; 8848 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8849 PetscFunctionReturn(PETSC_SUCCESS); 8850 } 8851 8852 /*@ 8853 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8854 8855 Neighbor-wise Collective 8856 8857 Input Parameters: 8858 + A - the matrix 8859 - x - the input dense matrix 8860 8861 Output Parameter: 8862 . y - the output dense matrix 8863 8864 Level: intermediate 8865 8866 Note: 8867 This allows one to use either the restriction or interpolation (its transpose) 8868 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8869 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8870 8871 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8872 @*/ 8873 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8874 { 8875 PetscFunctionBegin; 8876 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8877 PetscFunctionReturn(PETSC_SUCCESS); 8878 } 8879 8880 /*@ 8881 MatGetNullSpace - retrieves the null space of a matrix. 8882 8883 Logically Collective 8884 8885 Input Parameters: 8886 + mat - the matrix 8887 - nullsp - the null space object 8888 8889 Level: developer 8890 8891 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8892 @*/ 8893 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8894 { 8895 PetscFunctionBegin; 8896 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8897 PetscAssertPointer(nullsp, 2); 8898 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8899 PetscFunctionReturn(PETSC_SUCCESS); 8900 } 8901 8902 /*@C 8903 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8904 8905 Logically Collective 8906 8907 Input Parameters: 8908 + n - the number of matrices 8909 - mat - the array of matrices 8910 8911 Output Parameters: 8912 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8913 8914 Level: developer 8915 8916 Note: 8917 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8918 8919 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8920 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8921 @*/ 8922 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8923 { 8924 PetscFunctionBegin; 8925 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8926 PetscAssertPointer(mat, 2); 8927 PetscAssertPointer(nullsp, 3); 8928 8929 PetscCall(PetscCalloc1(3 * n, nullsp)); 8930 for (PetscInt i = 0; i < n; i++) { 8931 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8932 (*nullsp)[i] = mat[i]->nullsp; 8933 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8934 (*nullsp)[n + i] = mat[i]->nearnullsp; 8935 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8936 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8937 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8938 } 8939 PetscFunctionReturn(PETSC_SUCCESS); 8940 } 8941 8942 /*@C 8943 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8944 8945 Logically Collective 8946 8947 Input Parameters: 8948 + n - the number of matrices 8949 . mat - the array of matrices 8950 - nullsp - an array of null spaces 8951 8952 Level: developer 8953 8954 Note: 8955 Call `MatGetNullSpaces()` to create `nullsp` 8956 8957 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8958 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8959 @*/ 8960 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8961 { 8962 PetscFunctionBegin; 8963 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8964 PetscAssertPointer(mat, 2); 8965 PetscAssertPointer(nullsp, 3); 8966 PetscAssertPointer(*nullsp, 3); 8967 8968 for (PetscInt i = 0; i < n; i++) { 8969 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8970 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8971 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8972 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8973 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8974 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8975 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8976 } 8977 PetscCall(PetscFree(*nullsp)); 8978 PetscFunctionReturn(PETSC_SUCCESS); 8979 } 8980 8981 /*@ 8982 MatSetNullSpace - attaches a null space to a matrix. 8983 8984 Logically Collective 8985 8986 Input Parameters: 8987 + mat - the matrix 8988 - nullsp - the null space object 8989 8990 Level: advanced 8991 8992 Notes: 8993 This null space is used by the `KSP` linear solvers to solve singular systems. 8994 8995 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` 8996 8997 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 8998 to zero but the linear system will still be solved in a least squares sense. 8999 9000 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9001 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)$, plus the range of $A^T$, $R(A^T)$. 9002 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 9003 $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 9004 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)$. 9005 This $\hat{b}$ can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9006 9007 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one has called 9008 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9009 routine also automatically calls `MatSetTransposeNullSpace()`. 9010 9011 The user should call `MatNullSpaceDestroy()`. 9012 9013 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9014 `KSPSetPCSide()` 9015 @*/ 9016 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9017 { 9018 PetscFunctionBegin; 9019 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9020 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9021 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9022 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9023 mat->nullsp = nullsp; 9024 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9025 PetscFunctionReturn(PETSC_SUCCESS); 9026 } 9027 9028 /*@ 9029 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9030 9031 Logically Collective 9032 9033 Input Parameters: 9034 + mat - the matrix 9035 - nullsp - the null space object 9036 9037 Level: developer 9038 9039 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9040 @*/ 9041 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9042 { 9043 PetscFunctionBegin; 9044 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9045 PetscValidType(mat, 1); 9046 PetscAssertPointer(nullsp, 2); 9047 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9048 PetscFunctionReturn(PETSC_SUCCESS); 9049 } 9050 9051 /*@ 9052 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9053 9054 Logically Collective 9055 9056 Input Parameters: 9057 + mat - the matrix 9058 - nullsp - the null space object 9059 9060 Level: advanced 9061 9062 Notes: 9063 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9064 9065 See `MatSetNullSpace()` 9066 9067 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9068 @*/ 9069 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9070 { 9071 PetscFunctionBegin; 9072 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9073 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9074 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9075 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9076 mat->transnullsp = nullsp; 9077 PetscFunctionReturn(PETSC_SUCCESS); 9078 } 9079 9080 /*@ 9081 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9082 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9083 9084 Logically Collective 9085 9086 Input Parameters: 9087 + mat - the matrix 9088 - nullsp - the null space object 9089 9090 Level: advanced 9091 9092 Notes: 9093 Overwrites any previous near null space that may have been attached 9094 9095 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9096 9097 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9098 @*/ 9099 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9100 { 9101 PetscFunctionBegin; 9102 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9103 PetscValidType(mat, 1); 9104 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9105 MatCheckPreallocated(mat, 1); 9106 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9107 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9108 mat->nearnullsp = nullsp; 9109 PetscFunctionReturn(PETSC_SUCCESS); 9110 } 9111 9112 /*@ 9113 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9114 9115 Not Collective 9116 9117 Input Parameter: 9118 . mat - the matrix 9119 9120 Output Parameter: 9121 . nullsp - the null space object, `NULL` if not set 9122 9123 Level: advanced 9124 9125 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9126 @*/ 9127 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9128 { 9129 PetscFunctionBegin; 9130 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9131 PetscValidType(mat, 1); 9132 PetscAssertPointer(nullsp, 2); 9133 MatCheckPreallocated(mat, 1); 9134 *nullsp = mat->nearnullsp; 9135 PetscFunctionReturn(PETSC_SUCCESS); 9136 } 9137 9138 /*@ 9139 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9140 9141 Collective 9142 9143 Input Parameters: 9144 + mat - the matrix 9145 . row - row/column permutation 9146 - info - information on desired factorization process 9147 9148 Level: developer 9149 9150 Notes: 9151 Probably really in-place only when level of fill is zero, otherwise allocates 9152 new space to store factored matrix and deletes previous memory. 9153 9154 Most users should employ the `KSP` interface for linear solvers 9155 instead of working directly with matrix algebra routines such as this. 9156 See, e.g., `KSPCreate()`. 9157 9158 Fortran Note: 9159 A valid (non-null) `info` argument must be provided 9160 9161 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9162 @*/ 9163 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9164 { 9165 PetscFunctionBegin; 9166 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9167 PetscValidType(mat, 1); 9168 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9169 PetscAssertPointer(info, 3); 9170 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9171 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9172 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9173 MatCheckPreallocated(mat, 1); 9174 PetscUseTypeMethod(mat, iccfactor, row, info); 9175 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9176 PetscFunctionReturn(PETSC_SUCCESS); 9177 } 9178 9179 /*@ 9180 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9181 ghosted ones. 9182 9183 Not Collective 9184 9185 Input Parameters: 9186 + mat - the matrix 9187 - diag - the diagonal values, including ghost ones 9188 9189 Level: developer 9190 9191 Notes: 9192 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9193 9194 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9195 9196 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9197 @*/ 9198 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9199 { 9200 PetscMPIInt size; 9201 9202 PetscFunctionBegin; 9203 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9204 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9205 PetscValidType(mat, 1); 9206 9207 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9208 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9209 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9210 if (size == 1) { 9211 PetscInt n, m; 9212 PetscCall(VecGetSize(diag, &n)); 9213 PetscCall(MatGetSize(mat, NULL, &m)); 9214 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9215 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9216 } else { 9217 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9218 } 9219 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9220 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9221 PetscFunctionReturn(PETSC_SUCCESS); 9222 } 9223 9224 /*@ 9225 MatGetInertia - Gets the inertia from a factored matrix 9226 9227 Collective 9228 9229 Input Parameter: 9230 . mat - the matrix 9231 9232 Output Parameters: 9233 + nneg - number of negative eigenvalues 9234 . nzero - number of zero eigenvalues 9235 - npos - number of positive eigenvalues 9236 9237 Level: advanced 9238 9239 Note: 9240 Matrix must have been factored by `MatCholeskyFactor()` 9241 9242 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9243 @*/ 9244 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9245 { 9246 PetscFunctionBegin; 9247 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9248 PetscValidType(mat, 1); 9249 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9250 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9251 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9252 PetscFunctionReturn(PETSC_SUCCESS); 9253 } 9254 9255 /*@C 9256 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9257 9258 Neighbor-wise Collective 9259 9260 Input Parameters: 9261 + mat - the factored matrix obtained with `MatGetFactor()` 9262 - b - the right-hand-side vectors 9263 9264 Output Parameter: 9265 . x - the result vectors 9266 9267 Level: developer 9268 9269 Note: 9270 The vectors `b` and `x` cannot be the same. I.e., one cannot 9271 call `MatSolves`(A,x,x). 9272 9273 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9274 @*/ 9275 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9276 { 9277 PetscFunctionBegin; 9278 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9279 PetscValidType(mat, 1); 9280 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9281 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9282 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9283 9284 MatCheckPreallocated(mat, 1); 9285 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9286 PetscUseTypeMethod(mat, solves, b, x); 9287 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9288 PetscFunctionReturn(PETSC_SUCCESS); 9289 } 9290 9291 /*@ 9292 MatIsSymmetric - Test whether a matrix is symmetric 9293 9294 Collective 9295 9296 Input Parameters: 9297 + A - the matrix to test 9298 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9299 9300 Output Parameter: 9301 . flg - the result 9302 9303 Level: intermediate 9304 9305 Notes: 9306 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9307 9308 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9309 9310 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9311 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9312 9313 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9314 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9315 @*/ 9316 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9317 { 9318 PetscFunctionBegin; 9319 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9320 PetscAssertPointer(flg, 3); 9321 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9322 else { 9323 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9324 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9325 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9326 } 9327 PetscFunctionReturn(PETSC_SUCCESS); 9328 } 9329 9330 /*@ 9331 MatIsHermitian - Test whether a matrix is Hermitian 9332 9333 Collective 9334 9335 Input Parameters: 9336 + A - the matrix to test 9337 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9338 9339 Output Parameter: 9340 . flg - the result 9341 9342 Level: intermediate 9343 9344 Notes: 9345 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9346 9347 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9348 9349 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9350 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9351 9352 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9353 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9354 @*/ 9355 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9356 { 9357 PetscFunctionBegin; 9358 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9359 PetscAssertPointer(flg, 3); 9360 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9361 else { 9362 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9363 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9364 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9365 } 9366 PetscFunctionReturn(PETSC_SUCCESS); 9367 } 9368 9369 /*@ 9370 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9371 9372 Not Collective 9373 9374 Input Parameter: 9375 . A - the matrix to check 9376 9377 Output Parameters: 9378 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9379 - flg - the result (only valid if set is `PETSC_TRUE`) 9380 9381 Level: advanced 9382 9383 Notes: 9384 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9385 if you want it explicitly checked 9386 9387 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9388 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9389 9390 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9391 @*/ 9392 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9393 { 9394 PetscFunctionBegin; 9395 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9396 PetscAssertPointer(set, 2); 9397 PetscAssertPointer(flg, 3); 9398 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9399 *set = PETSC_TRUE; 9400 *flg = PetscBool3ToBool(A->symmetric); 9401 } else { 9402 *set = PETSC_FALSE; 9403 } 9404 PetscFunctionReturn(PETSC_SUCCESS); 9405 } 9406 9407 /*@ 9408 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9409 9410 Not Collective 9411 9412 Input Parameter: 9413 . A - the matrix to check 9414 9415 Output Parameters: 9416 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9417 - flg - the result (only valid if set is `PETSC_TRUE`) 9418 9419 Level: advanced 9420 9421 Notes: 9422 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9423 9424 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9425 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9426 9427 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9428 @*/ 9429 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9430 { 9431 PetscFunctionBegin; 9432 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9433 PetscAssertPointer(set, 2); 9434 PetscAssertPointer(flg, 3); 9435 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9436 *set = PETSC_TRUE; 9437 *flg = PetscBool3ToBool(A->spd); 9438 } else { 9439 *set = PETSC_FALSE; 9440 } 9441 PetscFunctionReturn(PETSC_SUCCESS); 9442 } 9443 9444 /*@ 9445 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9446 9447 Not Collective 9448 9449 Input Parameter: 9450 . A - the matrix to check 9451 9452 Output Parameters: 9453 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9454 - flg - the result (only valid if set is `PETSC_TRUE`) 9455 9456 Level: advanced 9457 9458 Notes: 9459 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9460 if you want it explicitly checked 9461 9462 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9463 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9464 9465 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9466 @*/ 9467 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9468 { 9469 PetscFunctionBegin; 9470 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9471 PetscAssertPointer(set, 2); 9472 PetscAssertPointer(flg, 3); 9473 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9474 *set = PETSC_TRUE; 9475 *flg = PetscBool3ToBool(A->hermitian); 9476 } else { 9477 *set = PETSC_FALSE; 9478 } 9479 PetscFunctionReturn(PETSC_SUCCESS); 9480 } 9481 9482 /*@ 9483 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9484 9485 Collective 9486 9487 Input Parameter: 9488 . A - the matrix to test 9489 9490 Output Parameter: 9491 . flg - the result 9492 9493 Level: intermediate 9494 9495 Notes: 9496 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9497 9498 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 9499 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9500 9501 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9502 @*/ 9503 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9504 { 9505 PetscFunctionBegin; 9506 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9507 PetscAssertPointer(flg, 2); 9508 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9509 *flg = PetscBool3ToBool(A->structurally_symmetric); 9510 } else { 9511 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9512 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9513 } 9514 PetscFunctionReturn(PETSC_SUCCESS); 9515 } 9516 9517 /*@ 9518 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9519 9520 Not Collective 9521 9522 Input Parameter: 9523 . A - the matrix to check 9524 9525 Output Parameters: 9526 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9527 - flg - the result (only valid if set is PETSC_TRUE) 9528 9529 Level: advanced 9530 9531 Notes: 9532 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 9533 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9534 9535 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9536 9537 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9538 @*/ 9539 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9540 { 9541 PetscFunctionBegin; 9542 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9543 PetscAssertPointer(set, 2); 9544 PetscAssertPointer(flg, 3); 9545 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9546 *set = PETSC_TRUE; 9547 *flg = PetscBool3ToBool(A->structurally_symmetric); 9548 } else { 9549 *set = PETSC_FALSE; 9550 } 9551 PetscFunctionReturn(PETSC_SUCCESS); 9552 } 9553 9554 /*@ 9555 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9556 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9557 9558 Not Collective 9559 9560 Input Parameter: 9561 . mat - the matrix 9562 9563 Output Parameters: 9564 + nstash - the size of the stash 9565 . reallocs - the number of additional mallocs incurred. 9566 . bnstash - the size of the block stash 9567 - breallocs - the number of additional mallocs incurred.in the block stash 9568 9569 Level: advanced 9570 9571 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9572 @*/ 9573 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9574 { 9575 PetscFunctionBegin; 9576 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9577 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9578 PetscFunctionReturn(PETSC_SUCCESS); 9579 } 9580 9581 /*@ 9582 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9583 parallel layout, `PetscLayout` for rows and columns 9584 9585 Collective 9586 9587 Input Parameter: 9588 . mat - the matrix 9589 9590 Output Parameters: 9591 + right - (optional) vector that the matrix can be multiplied against 9592 - left - (optional) vector that the matrix vector product can be stored in 9593 9594 Level: advanced 9595 9596 Notes: 9597 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()`. 9598 9599 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9600 9601 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9602 @*/ 9603 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9604 { 9605 PetscFunctionBegin; 9606 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9607 PetscValidType(mat, 1); 9608 if (mat->ops->getvecs) { 9609 PetscUseTypeMethod(mat, getvecs, right, left); 9610 } else { 9611 if (right) { 9612 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9613 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9614 PetscCall(VecSetType(*right, mat->defaultvectype)); 9615 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9616 if (mat->boundtocpu && mat->bindingpropagates) { 9617 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9618 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9619 } 9620 #endif 9621 } 9622 if (left) { 9623 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9624 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9625 PetscCall(VecSetType(*left, mat->defaultvectype)); 9626 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9627 if (mat->boundtocpu && mat->bindingpropagates) { 9628 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9629 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9630 } 9631 #endif 9632 } 9633 } 9634 PetscFunctionReturn(PETSC_SUCCESS); 9635 } 9636 9637 /*@ 9638 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9639 with default values. 9640 9641 Not Collective 9642 9643 Input Parameter: 9644 . info - the `MatFactorInfo` data structure 9645 9646 Level: developer 9647 9648 Notes: 9649 The solvers are generally used through the `KSP` and `PC` objects, for example 9650 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9651 9652 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9653 9654 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9655 @*/ 9656 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9657 { 9658 PetscFunctionBegin; 9659 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9660 PetscFunctionReturn(PETSC_SUCCESS); 9661 } 9662 9663 /*@ 9664 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9665 9666 Collective 9667 9668 Input Parameters: 9669 + mat - the factored matrix 9670 - is - the index set defining the Schur indices (0-based) 9671 9672 Level: advanced 9673 9674 Notes: 9675 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9676 9677 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9678 9679 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9680 9681 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9682 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9683 @*/ 9684 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9685 { 9686 PetscErrorCode (*f)(Mat, IS); 9687 9688 PetscFunctionBegin; 9689 PetscValidType(mat, 1); 9690 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9691 PetscValidType(is, 2); 9692 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9693 PetscCheckSameComm(mat, 1, is, 2); 9694 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9695 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9696 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9697 PetscCall(MatDestroy(&mat->schur)); 9698 PetscCall((*f)(mat, is)); 9699 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9700 PetscFunctionReturn(PETSC_SUCCESS); 9701 } 9702 9703 /*@ 9704 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9705 9706 Logically Collective 9707 9708 Input Parameters: 9709 + F - the factored matrix obtained by calling `MatGetFactor()` 9710 . S - location where to return the Schur complement, can be `NULL` 9711 - status - the status of the Schur complement matrix, can be `NULL` 9712 9713 Level: advanced 9714 9715 Notes: 9716 You must call `MatFactorSetSchurIS()` before calling this routine. 9717 9718 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9719 9720 The routine provides a copy of the Schur matrix stored within the solver data structures. 9721 The caller must destroy the object when it is no longer needed. 9722 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9723 9724 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) 9725 9726 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9727 9728 Developer Note: 9729 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9730 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9731 9732 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9733 @*/ 9734 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9735 { 9736 PetscFunctionBegin; 9737 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9738 if (S) PetscAssertPointer(S, 2); 9739 if (status) PetscAssertPointer(status, 3); 9740 if (S) { 9741 PetscErrorCode (*f)(Mat, Mat *); 9742 9743 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9744 if (f) { 9745 PetscCall((*f)(F, S)); 9746 } else { 9747 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9748 } 9749 } 9750 if (status) *status = F->schur_status; 9751 PetscFunctionReturn(PETSC_SUCCESS); 9752 } 9753 9754 /*@ 9755 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9756 9757 Logically Collective 9758 9759 Input Parameters: 9760 + F - the factored matrix obtained by calling `MatGetFactor()` 9761 . S - location where to return the Schur complement, can be `NULL` 9762 - status - the status of the Schur complement matrix, can be `NULL` 9763 9764 Level: advanced 9765 9766 Notes: 9767 You must call `MatFactorSetSchurIS()` before calling this routine. 9768 9769 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9770 9771 The routine returns a the Schur Complement stored within the data structures of the solver. 9772 9773 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9774 9775 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9776 9777 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9778 9779 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9780 9781 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9782 @*/ 9783 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9784 { 9785 PetscFunctionBegin; 9786 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9787 if (S) { 9788 PetscAssertPointer(S, 2); 9789 *S = F->schur; 9790 } 9791 if (status) { 9792 PetscAssertPointer(status, 3); 9793 *status = F->schur_status; 9794 } 9795 PetscFunctionReturn(PETSC_SUCCESS); 9796 } 9797 9798 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9799 { 9800 Mat S = F->schur; 9801 9802 PetscFunctionBegin; 9803 switch (F->schur_status) { 9804 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9805 case MAT_FACTOR_SCHUR_INVERTED: 9806 if (S) { 9807 S->ops->solve = NULL; 9808 S->ops->matsolve = NULL; 9809 S->ops->solvetranspose = NULL; 9810 S->ops->matsolvetranspose = NULL; 9811 S->ops->solveadd = NULL; 9812 S->ops->solvetransposeadd = NULL; 9813 S->factortype = MAT_FACTOR_NONE; 9814 PetscCall(PetscFree(S->solvertype)); 9815 } 9816 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9817 break; 9818 default: 9819 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9820 } 9821 PetscFunctionReturn(PETSC_SUCCESS); 9822 } 9823 9824 /*@ 9825 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9826 9827 Logically Collective 9828 9829 Input Parameters: 9830 + F - the factored matrix obtained by calling `MatGetFactor()` 9831 . S - location where the Schur complement is stored 9832 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9833 9834 Level: advanced 9835 9836 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9837 @*/ 9838 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9839 { 9840 PetscFunctionBegin; 9841 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9842 if (S) { 9843 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9844 *S = NULL; 9845 } 9846 F->schur_status = status; 9847 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9848 PetscFunctionReturn(PETSC_SUCCESS); 9849 } 9850 9851 /*@ 9852 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9853 9854 Logically Collective 9855 9856 Input Parameters: 9857 + F - the factored matrix obtained by calling `MatGetFactor()` 9858 . rhs - location where the right-hand side of the Schur complement system is stored 9859 - sol - location where the solution of the Schur complement system has to be returned 9860 9861 Level: advanced 9862 9863 Notes: 9864 The sizes of the vectors should match the size of the Schur complement 9865 9866 Must be called after `MatFactorSetSchurIS()` 9867 9868 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9869 @*/ 9870 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9871 { 9872 PetscFunctionBegin; 9873 PetscValidType(F, 1); 9874 PetscValidType(rhs, 2); 9875 PetscValidType(sol, 3); 9876 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9877 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9878 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9879 PetscCheckSameComm(F, 1, rhs, 2); 9880 PetscCheckSameComm(F, 1, sol, 3); 9881 PetscCall(MatFactorFactorizeSchurComplement(F)); 9882 switch (F->schur_status) { 9883 case MAT_FACTOR_SCHUR_FACTORED: 9884 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9885 break; 9886 case MAT_FACTOR_SCHUR_INVERTED: 9887 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9888 break; 9889 default: 9890 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9891 } 9892 PetscFunctionReturn(PETSC_SUCCESS); 9893 } 9894 9895 /*@ 9896 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9897 9898 Logically Collective 9899 9900 Input Parameters: 9901 + F - the factored matrix obtained by calling `MatGetFactor()` 9902 . rhs - location where the right-hand side of the Schur complement system is stored 9903 - sol - location where the solution of the Schur complement system has to be returned 9904 9905 Level: advanced 9906 9907 Notes: 9908 The sizes of the vectors should match the size of the Schur complement 9909 9910 Must be called after `MatFactorSetSchurIS()` 9911 9912 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9913 @*/ 9914 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9915 { 9916 PetscFunctionBegin; 9917 PetscValidType(F, 1); 9918 PetscValidType(rhs, 2); 9919 PetscValidType(sol, 3); 9920 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9921 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9922 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9923 PetscCheckSameComm(F, 1, rhs, 2); 9924 PetscCheckSameComm(F, 1, sol, 3); 9925 PetscCall(MatFactorFactorizeSchurComplement(F)); 9926 switch (F->schur_status) { 9927 case MAT_FACTOR_SCHUR_FACTORED: 9928 PetscCall(MatSolve(F->schur, rhs, sol)); 9929 break; 9930 case MAT_FACTOR_SCHUR_INVERTED: 9931 PetscCall(MatMult(F->schur, rhs, sol)); 9932 break; 9933 default: 9934 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9935 } 9936 PetscFunctionReturn(PETSC_SUCCESS); 9937 } 9938 9939 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9940 #if PetscDefined(HAVE_CUDA) 9941 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9942 #endif 9943 9944 /* Schur status updated in the interface */ 9945 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9946 { 9947 Mat S = F->schur; 9948 9949 PetscFunctionBegin; 9950 if (S) { 9951 PetscMPIInt size; 9952 PetscBool isdense, isdensecuda; 9953 9954 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9955 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9956 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9957 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9958 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9959 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9960 if (isdense) { 9961 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9962 } else if (isdensecuda) { 9963 #if defined(PETSC_HAVE_CUDA) 9964 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9965 #endif 9966 } 9967 // HIP?????????????? 9968 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9969 } 9970 PetscFunctionReturn(PETSC_SUCCESS); 9971 } 9972 9973 /*@ 9974 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9975 9976 Logically Collective 9977 9978 Input Parameter: 9979 . F - the factored matrix obtained by calling `MatGetFactor()` 9980 9981 Level: advanced 9982 9983 Notes: 9984 Must be called after `MatFactorSetSchurIS()`. 9985 9986 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9987 9988 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9989 @*/ 9990 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9991 { 9992 PetscFunctionBegin; 9993 PetscValidType(F, 1); 9994 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9995 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9996 PetscCall(MatFactorFactorizeSchurComplement(F)); 9997 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9998 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9999 PetscFunctionReturn(PETSC_SUCCESS); 10000 } 10001 10002 /*@ 10003 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10004 10005 Logically Collective 10006 10007 Input Parameter: 10008 . F - the factored matrix obtained by calling `MatGetFactor()` 10009 10010 Level: advanced 10011 10012 Note: 10013 Must be called after `MatFactorSetSchurIS()` 10014 10015 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10016 @*/ 10017 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10018 { 10019 MatFactorInfo info; 10020 10021 PetscFunctionBegin; 10022 PetscValidType(F, 1); 10023 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10024 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10025 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10026 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10027 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10028 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10029 } else { 10030 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10031 } 10032 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10033 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10034 PetscFunctionReturn(PETSC_SUCCESS); 10035 } 10036 10037 /*@ 10038 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10039 10040 Neighbor-wise Collective 10041 10042 Input Parameters: 10043 + A - the matrix 10044 . P - the projection matrix 10045 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10046 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10047 if the result is a dense matrix this is irrelevant 10048 10049 Output Parameter: 10050 . C - the product matrix 10051 10052 Level: intermediate 10053 10054 Notes: 10055 C will be created and must be destroyed by the user with `MatDestroy()`. 10056 10057 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10058 10059 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10060 10061 Developer Note: 10062 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10063 10064 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10065 @*/ 10066 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10067 { 10068 PetscFunctionBegin; 10069 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10070 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10071 10072 if (scall == MAT_INITIAL_MATRIX) { 10073 PetscCall(MatProductCreate(A, P, NULL, C)); 10074 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10075 PetscCall(MatProductSetAlgorithm(*C, "default")); 10076 PetscCall(MatProductSetFill(*C, fill)); 10077 10078 (*C)->product->api_user = PETSC_TRUE; 10079 PetscCall(MatProductSetFromOptions(*C)); 10080 PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "MatProduct %s not supported for A %s and P %s", MatProductTypes[MATPRODUCT_PtAP], ((PetscObject)A)->type_name, ((PetscObject)P)->type_name); 10081 PetscCall(MatProductSymbolic(*C)); 10082 } else { /* scall == MAT_REUSE_MATRIX */ 10083 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10084 } 10085 10086 PetscCall(MatProductNumeric(*C)); 10087 (*C)->symmetric = A->symmetric; 10088 (*C)->spd = A->spd; 10089 PetscFunctionReturn(PETSC_SUCCESS); 10090 } 10091 10092 /*@ 10093 MatRARt - Creates the matrix product $C = R * A * R^T$ 10094 10095 Neighbor-wise Collective 10096 10097 Input Parameters: 10098 + A - the matrix 10099 . R - the projection matrix 10100 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10101 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10102 if the result is a dense matrix this is irrelevant 10103 10104 Output Parameter: 10105 . C - the product matrix 10106 10107 Level: intermediate 10108 10109 Notes: 10110 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10111 10112 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10113 10114 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10115 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10116 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10117 We recommend using `MatPtAP()` when possible. 10118 10119 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10120 10121 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10122 @*/ 10123 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10124 { 10125 PetscFunctionBegin; 10126 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10127 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10128 10129 if (scall == MAT_INITIAL_MATRIX) { 10130 PetscCall(MatProductCreate(A, R, NULL, C)); 10131 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10132 PetscCall(MatProductSetAlgorithm(*C, "default")); 10133 PetscCall(MatProductSetFill(*C, fill)); 10134 10135 (*C)->product->api_user = PETSC_TRUE; 10136 PetscCall(MatProductSetFromOptions(*C)); 10137 PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "MatProduct %s not supported for A %s and R %s", MatProductTypes[MATPRODUCT_RARt], ((PetscObject)A)->type_name, ((PetscObject)R)->type_name); 10138 PetscCall(MatProductSymbolic(*C)); 10139 } else { /* scall == MAT_REUSE_MATRIX */ 10140 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10141 } 10142 10143 PetscCall(MatProductNumeric(*C)); 10144 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10145 PetscFunctionReturn(PETSC_SUCCESS); 10146 } 10147 10148 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10149 { 10150 PetscBool flg = PETSC_TRUE; 10151 10152 PetscFunctionBegin; 10153 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10154 if (scall == MAT_INITIAL_MATRIX) { 10155 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10156 PetscCall(MatProductCreate(A, B, NULL, C)); 10157 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10158 PetscCall(MatProductSetFill(*C, fill)); 10159 } else { /* scall == MAT_REUSE_MATRIX */ 10160 Mat_Product *product = (*C)->product; 10161 10162 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10163 if (flg && product && product->type != ptype) { 10164 PetscCall(MatProductClear(*C)); 10165 product = NULL; 10166 } 10167 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10168 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10169 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10170 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10171 product = (*C)->product; 10172 product->fill = fill; 10173 product->clear = PETSC_TRUE; 10174 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10175 flg = PETSC_FALSE; 10176 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10177 } 10178 } 10179 if (flg) { 10180 (*C)->product->api_user = PETSC_TRUE; 10181 PetscCall(MatProductSetType(*C, ptype)); 10182 PetscCall(MatProductSetFromOptions(*C)); 10183 PetscCall(MatProductSymbolic(*C)); 10184 } 10185 PetscCall(MatProductNumeric(*C)); 10186 PetscFunctionReturn(PETSC_SUCCESS); 10187 } 10188 10189 /*@ 10190 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10191 10192 Neighbor-wise Collective 10193 10194 Input Parameters: 10195 + A - the left matrix 10196 . B - the right matrix 10197 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10198 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10199 if the result is a dense matrix this is irrelevant 10200 10201 Output Parameter: 10202 . C - the product matrix 10203 10204 Notes: 10205 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10206 10207 `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 10208 call to this function with `MAT_INITIAL_MATRIX`. 10209 10210 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10211 10212 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`, 10213 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10214 10215 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10216 10217 Example of Usage: 10218 .vb 10219 MatProductCreate(A,B,NULL,&C); 10220 MatProductSetType(C,MATPRODUCT_AB); 10221 MatProductSymbolic(C); 10222 MatProductNumeric(C); // compute C=A * B 10223 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10224 MatProductNumeric(C); 10225 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10226 MatProductNumeric(C); 10227 .ve 10228 10229 Level: intermediate 10230 10231 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10232 @*/ 10233 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10234 { 10235 PetscFunctionBegin; 10236 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10237 PetscFunctionReturn(PETSC_SUCCESS); 10238 } 10239 10240 /*@ 10241 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10242 10243 Neighbor-wise Collective 10244 10245 Input Parameters: 10246 + A - the left matrix 10247 . B - the right matrix 10248 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10249 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10250 10251 Output Parameter: 10252 . C - the product matrix 10253 10254 Options Database Key: 10255 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10256 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10257 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10258 10259 Level: intermediate 10260 10261 Notes: 10262 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10263 10264 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10265 10266 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10267 actually needed. 10268 10269 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10270 and for pairs of `MATMPIDENSE` matrices. 10271 10272 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10273 10274 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10275 10276 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10277 @*/ 10278 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10279 { 10280 PetscFunctionBegin; 10281 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10282 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10283 PetscFunctionReturn(PETSC_SUCCESS); 10284 } 10285 10286 /*@ 10287 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10288 10289 Neighbor-wise Collective 10290 10291 Input Parameters: 10292 + A - the left matrix 10293 . B - the right matrix 10294 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10295 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10296 10297 Output Parameter: 10298 . C - the product matrix 10299 10300 Level: intermediate 10301 10302 Notes: 10303 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10304 10305 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10306 10307 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10308 10309 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10310 actually needed. 10311 10312 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10313 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10314 10315 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10316 10317 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10318 @*/ 10319 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10320 { 10321 PetscFunctionBegin; 10322 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10323 PetscFunctionReturn(PETSC_SUCCESS); 10324 } 10325 10326 /*@ 10327 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10328 10329 Neighbor-wise Collective 10330 10331 Input Parameters: 10332 + A - the left matrix 10333 . B - the middle matrix 10334 . C - the right matrix 10335 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10336 - fill - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10337 if the result is a dense matrix this is irrelevant 10338 10339 Output Parameter: 10340 . D - the product matrix 10341 10342 Level: intermediate 10343 10344 Notes: 10345 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10346 10347 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10348 10349 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10350 10351 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10352 actually needed. 10353 10354 If you have many matrices with the same non-zero structure to multiply, you 10355 should use `MAT_REUSE_MATRIX` in all calls but the first 10356 10357 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10358 10359 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10360 @*/ 10361 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10362 { 10363 PetscFunctionBegin; 10364 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10365 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10366 10367 if (scall == MAT_INITIAL_MATRIX) { 10368 PetscCall(MatProductCreate(A, B, C, D)); 10369 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10370 PetscCall(MatProductSetAlgorithm(*D, "default")); 10371 PetscCall(MatProductSetFill(*D, fill)); 10372 10373 (*D)->product->api_user = PETSC_TRUE; 10374 PetscCall(MatProductSetFromOptions(*D)); 10375 PetscCheck((*D)->ops->productsymbolic, PetscObjectComm((PetscObject)*D), PETSC_ERR_SUP, "MatProduct %s not supported for A %s, B %s and C %s", MatProductTypes[MATPRODUCT_ABC], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name, 10376 ((PetscObject)C)->type_name); 10377 PetscCall(MatProductSymbolic(*D)); 10378 } else { /* user may change input matrices when REUSE */ 10379 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10380 } 10381 PetscCall(MatProductNumeric(*D)); 10382 PetscFunctionReturn(PETSC_SUCCESS); 10383 } 10384 10385 /*@ 10386 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10387 10388 Collective 10389 10390 Input Parameters: 10391 + mat - the matrix 10392 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10393 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10394 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10395 10396 Output Parameter: 10397 . matredundant - redundant matrix 10398 10399 Level: advanced 10400 10401 Notes: 10402 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10403 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10404 10405 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10406 calling it. 10407 10408 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10409 10410 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10411 @*/ 10412 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10413 { 10414 MPI_Comm comm; 10415 PetscMPIInt size; 10416 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10417 Mat_Redundant *redund = NULL; 10418 PetscSubcomm psubcomm = NULL; 10419 MPI_Comm subcomm_in = subcomm; 10420 Mat *matseq; 10421 IS isrow, iscol; 10422 PetscBool newsubcomm = PETSC_FALSE; 10423 10424 PetscFunctionBegin; 10425 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10426 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10427 PetscAssertPointer(*matredundant, 5); 10428 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10429 } 10430 10431 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10432 if (size == 1 || nsubcomm == 1) { 10433 if (reuse == MAT_INITIAL_MATRIX) { 10434 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10435 } else { 10436 PetscCheck(*matredundant != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix"); 10437 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10438 } 10439 PetscFunctionReturn(PETSC_SUCCESS); 10440 } 10441 10442 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10443 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10444 MatCheckPreallocated(mat, 1); 10445 10446 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10447 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10448 /* create psubcomm, then get subcomm */ 10449 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10450 PetscCallMPI(MPI_Comm_size(comm, &size)); 10451 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10452 10453 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10454 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10455 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10456 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10457 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10458 newsubcomm = PETSC_TRUE; 10459 PetscCall(PetscSubcommDestroy(&psubcomm)); 10460 } 10461 10462 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10463 if (reuse == MAT_INITIAL_MATRIX) { 10464 mloc_sub = PETSC_DECIDE; 10465 nloc_sub = PETSC_DECIDE; 10466 if (bs < 1) { 10467 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10468 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10469 } else { 10470 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10471 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10472 } 10473 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10474 rstart = rend - mloc_sub; 10475 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10476 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10477 PetscCall(ISSetIdentity(iscol)); 10478 } else { /* reuse == MAT_REUSE_MATRIX */ 10479 PetscCheck(*matredundant != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix"); 10480 /* retrieve subcomm */ 10481 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10482 redund = (*matredundant)->redundant; 10483 isrow = redund->isrow; 10484 iscol = redund->iscol; 10485 matseq = redund->matseq; 10486 } 10487 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10488 10489 /* get matredundant over subcomm */ 10490 if (reuse == MAT_INITIAL_MATRIX) { 10491 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10492 10493 /* create a supporting struct and attach it to C for reuse */ 10494 PetscCall(PetscNew(&redund)); 10495 (*matredundant)->redundant = redund; 10496 redund->isrow = isrow; 10497 redund->iscol = iscol; 10498 redund->matseq = matseq; 10499 if (newsubcomm) { 10500 redund->subcomm = subcomm; 10501 } else { 10502 redund->subcomm = MPI_COMM_NULL; 10503 } 10504 } else { 10505 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10506 } 10507 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10508 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10509 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10510 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10511 } 10512 #endif 10513 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10514 PetscFunctionReturn(PETSC_SUCCESS); 10515 } 10516 10517 /*@C 10518 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10519 a given `Mat`. Each submatrix can span multiple procs. 10520 10521 Collective 10522 10523 Input Parameters: 10524 + mat - the matrix 10525 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10526 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10527 10528 Output Parameter: 10529 . subMat - parallel sub-matrices each spanning a given `subcomm` 10530 10531 Level: advanced 10532 10533 Notes: 10534 The submatrix partition across processors is dictated by `subComm` a 10535 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10536 is not restricted to be grouped with consecutive original MPI processes. 10537 10538 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10539 map directly to the layout of the original matrix [wrt the local 10540 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10541 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10542 the `subMat`. However the offDiagMat looses some columns - and this is 10543 reconstructed with `MatSetValues()` 10544 10545 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10546 10547 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10548 @*/ 10549 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10550 { 10551 PetscMPIInt commsize, subCommSize; 10552 10553 PetscFunctionBegin; 10554 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10555 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10556 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10557 10558 PetscCheck(scall != MAT_REUSE_MATRIX || *subMat != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix"); 10559 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10560 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10561 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10562 PetscFunctionReturn(PETSC_SUCCESS); 10563 } 10564 10565 /*@ 10566 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10567 10568 Not Collective 10569 10570 Input Parameters: 10571 + mat - matrix to extract local submatrix from 10572 . isrow - local row indices for submatrix 10573 - iscol - local column indices for submatrix 10574 10575 Output Parameter: 10576 . submat - the submatrix 10577 10578 Level: intermediate 10579 10580 Notes: 10581 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10582 10583 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10584 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10585 10586 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10587 `MatSetValuesBlockedLocal()` will also be implemented. 10588 10589 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10590 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10591 10592 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10593 @*/ 10594 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10595 { 10596 PetscFunctionBegin; 10597 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10598 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10599 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10600 PetscCheckSameComm(isrow, 2, iscol, 3); 10601 PetscAssertPointer(submat, 4); 10602 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10603 10604 if (mat->ops->getlocalsubmatrix) { 10605 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10606 } else { 10607 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10608 } 10609 PetscFunctionReturn(PETSC_SUCCESS); 10610 } 10611 10612 /*@ 10613 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10614 10615 Not Collective 10616 10617 Input Parameters: 10618 + mat - matrix to extract local submatrix from 10619 . isrow - local row indices for submatrix 10620 . iscol - local column indices for submatrix 10621 - submat - the submatrix 10622 10623 Level: intermediate 10624 10625 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10626 @*/ 10627 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10628 { 10629 PetscFunctionBegin; 10630 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10631 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10632 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10633 PetscCheckSameComm(isrow, 2, iscol, 3); 10634 PetscAssertPointer(submat, 4); 10635 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10636 10637 if (mat->ops->restorelocalsubmatrix) { 10638 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10639 } else { 10640 PetscCall(MatDestroy(submat)); 10641 } 10642 *submat = NULL; 10643 PetscFunctionReturn(PETSC_SUCCESS); 10644 } 10645 10646 /*@ 10647 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10648 10649 Collective 10650 10651 Input Parameter: 10652 . mat - the matrix 10653 10654 Output Parameter: 10655 . is - if any rows have zero diagonals this contains the list of them 10656 10657 Level: developer 10658 10659 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10660 @*/ 10661 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10662 { 10663 PetscFunctionBegin; 10664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10665 PetscValidType(mat, 1); 10666 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10667 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10668 10669 if (!mat->ops->findzerodiagonals) { 10670 Vec diag; 10671 const PetscScalar *a; 10672 PetscInt *rows; 10673 PetscInt rStart, rEnd, r, nrow = 0; 10674 10675 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10676 PetscCall(MatGetDiagonal(mat, diag)); 10677 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10678 PetscCall(VecGetArrayRead(diag, &a)); 10679 for (r = 0; r < rEnd - rStart; ++r) 10680 if (a[r] == 0.0) ++nrow; 10681 PetscCall(PetscMalloc1(nrow, &rows)); 10682 nrow = 0; 10683 for (r = 0; r < rEnd - rStart; ++r) 10684 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10685 PetscCall(VecRestoreArrayRead(diag, &a)); 10686 PetscCall(VecDestroy(&diag)); 10687 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10688 } else { 10689 PetscUseTypeMethod(mat, findzerodiagonals, is); 10690 } 10691 PetscFunctionReturn(PETSC_SUCCESS); 10692 } 10693 10694 /*@ 10695 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10696 10697 Collective 10698 10699 Input Parameter: 10700 . mat - the matrix 10701 10702 Output Parameter: 10703 . is - contains the list of rows with off block diagonal entries 10704 10705 Level: developer 10706 10707 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10708 @*/ 10709 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10710 { 10711 PetscFunctionBegin; 10712 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10713 PetscValidType(mat, 1); 10714 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10715 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10716 10717 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10718 PetscFunctionReturn(PETSC_SUCCESS); 10719 } 10720 10721 /*@C 10722 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10723 10724 Collective; No Fortran Support 10725 10726 Input Parameter: 10727 . mat - the matrix 10728 10729 Output Parameter: 10730 . values - the block inverses in column major order (FORTRAN-like) 10731 10732 Level: advanced 10733 10734 Notes: 10735 The size of the blocks is determined by the block size of the matrix. 10736 10737 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10738 10739 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10740 10741 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10742 @*/ 10743 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10744 { 10745 PetscFunctionBegin; 10746 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10747 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10748 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10749 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10750 PetscFunctionReturn(PETSC_SUCCESS); 10751 } 10752 10753 /*@ 10754 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10755 10756 Collective; No Fortran Support 10757 10758 Input Parameters: 10759 + mat - the matrix 10760 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10761 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10762 10763 Output Parameter: 10764 . values - the block inverses in column major order (FORTRAN-like) 10765 10766 Level: advanced 10767 10768 Notes: 10769 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10770 10771 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10772 10773 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10774 @*/ 10775 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10776 { 10777 PetscFunctionBegin; 10778 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10779 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10780 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10781 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10782 PetscFunctionReturn(PETSC_SUCCESS); 10783 } 10784 10785 /*@ 10786 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10787 10788 Collective 10789 10790 Input Parameters: 10791 + A - the matrix 10792 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10793 10794 Level: advanced 10795 10796 Note: 10797 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10798 10799 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10800 @*/ 10801 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10802 { 10803 const PetscScalar *vals; 10804 PetscInt *dnnz; 10805 PetscInt m, rstart, rend, bs, i, j; 10806 10807 PetscFunctionBegin; 10808 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10809 PetscCall(MatGetBlockSize(A, &bs)); 10810 PetscCall(MatGetLocalSize(A, &m, NULL)); 10811 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10812 PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); 10813 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10814 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10815 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10816 PetscCall(PetscFree(dnnz)); 10817 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10818 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10819 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10820 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10821 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10822 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10823 PetscFunctionReturn(PETSC_SUCCESS); 10824 } 10825 10826 /*@ 10827 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10828 via `MatTransposeColoringCreate()`. 10829 10830 Collective 10831 10832 Input Parameter: 10833 . c - coloring context 10834 10835 Level: intermediate 10836 10837 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10838 @*/ 10839 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10840 { 10841 MatTransposeColoring matcolor = *c; 10842 10843 PetscFunctionBegin; 10844 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10845 if (--((PetscObject)matcolor)->refct > 0) { 10846 matcolor = NULL; 10847 PetscFunctionReturn(PETSC_SUCCESS); 10848 } 10849 10850 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10851 PetscCall(PetscFree(matcolor->rows)); 10852 PetscCall(PetscFree(matcolor->den2sp)); 10853 PetscCall(PetscFree(matcolor->colorforcol)); 10854 PetscCall(PetscFree(matcolor->columns)); 10855 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10856 PetscCall(PetscHeaderDestroy(c)); 10857 PetscFunctionReturn(PETSC_SUCCESS); 10858 } 10859 10860 /*@ 10861 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10862 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10863 `MatTransposeColoring` to sparse `B`. 10864 10865 Collective 10866 10867 Input Parameters: 10868 + coloring - coloring context created with `MatTransposeColoringCreate()` 10869 - B - sparse matrix 10870 10871 Output Parameter: 10872 . Btdense - dense matrix $B^T$ 10873 10874 Level: developer 10875 10876 Note: 10877 These are used internally for some implementations of `MatRARt()` 10878 10879 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10880 @*/ 10881 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10882 { 10883 PetscFunctionBegin; 10884 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10885 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10886 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10887 10888 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10889 PetscFunctionReturn(PETSC_SUCCESS); 10890 } 10891 10892 /*@ 10893 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10894 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10895 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10896 $C_{sp}$ from $C_{den}$. 10897 10898 Collective 10899 10900 Input Parameters: 10901 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10902 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10903 10904 Output Parameter: 10905 . Csp - sparse matrix 10906 10907 Level: developer 10908 10909 Note: 10910 These are used internally for some implementations of `MatRARt()` 10911 10912 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10913 @*/ 10914 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10915 { 10916 PetscFunctionBegin; 10917 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10918 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10919 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10920 10921 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10922 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10923 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10924 PetscFunctionReturn(PETSC_SUCCESS); 10925 } 10926 10927 /*@ 10928 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10929 10930 Collective 10931 10932 Input Parameters: 10933 + mat - the matrix product C 10934 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10935 10936 Output Parameter: 10937 . color - the new coloring context 10938 10939 Level: intermediate 10940 10941 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10942 `MatTransColoringApplyDenToSp()` 10943 @*/ 10944 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10945 { 10946 MatTransposeColoring c; 10947 MPI_Comm comm; 10948 10949 PetscFunctionBegin; 10950 PetscAssertPointer(color, 3); 10951 10952 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10953 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10954 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10955 c->ctype = iscoloring->ctype; 10956 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10957 *color = c; 10958 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10959 PetscFunctionReturn(PETSC_SUCCESS); 10960 } 10961 10962 /*@ 10963 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10964 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10965 10966 Not Collective 10967 10968 Input Parameter: 10969 . mat - the matrix 10970 10971 Output Parameter: 10972 . state - the current state 10973 10974 Level: intermediate 10975 10976 Notes: 10977 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10978 different matrices 10979 10980 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10981 10982 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10983 10984 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10985 @*/ 10986 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10987 { 10988 PetscFunctionBegin; 10989 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10990 *state = mat->nonzerostate; 10991 PetscFunctionReturn(PETSC_SUCCESS); 10992 } 10993 10994 /*@ 10995 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10996 matrices from each processor 10997 10998 Collective 10999 11000 Input Parameters: 11001 + comm - the communicators the parallel matrix will live on 11002 . seqmat - the input sequential matrices 11003 . n - number of local columns (or `PETSC_DECIDE`) 11004 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11005 11006 Output Parameter: 11007 . mpimat - the parallel matrix generated 11008 11009 Level: developer 11010 11011 Note: 11012 The number of columns of the matrix in EACH processor MUST be the same. 11013 11014 .seealso: [](ch_matrices), `Mat` 11015 @*/ 11016 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11017 { 11018 PetscMPIInt size; 11019 11020 PetscFunctionBegin; 11021 PetscCallMPI(MPI_Comm_size(comm, &size)); 11022 if (size == 1) { 11023 if (reuse == MAT_INITIAL_MATRIX) { 11024 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11025 } else { 11026 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11027 } 11028 PetscFunctionReturn(PETSC_SUCCESS); 11029 } 11030 11031 PetscCheck(reuse != MAT_REUSE_MATRIX || seqmat != *mpimat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix"); 11032 11033 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11034 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11035 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11036 PetscFunctionReturn(PETSC_SUCCESS); 11037 } 11038 11039 /*@ 11040 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11041 11042 Collective 11043 11044 Input Parameters: 11045 + A - the matrix to create subdomains from 11046 - N - requested number of subdomains 11047 11048 Output Parameters: 11049 + n - number of subdomains resulting on this MPI process 11050 - iss - `IS` list with indices of subdomains on this MPI process 11051 11052 Level: advanced 11053 11054 Note: 11055 The number of subdomains must be smaller than the communicator size 11056 11057 .seealso: [](ch_matrices), `Mat`, `IS` 11058 @*/ 11059 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11060 { 11061 MPI_Comm comm, subcomm; 11062 PetscMPIInt size, rank, color; 11063 PetscInt rstart, rend, k; 11064 11065 PetscFunctionBegin; 11066 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11067 PetscCallMPI(MPI_Comm_size(comm, &size)); 11068 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11069 PetscCheck(N >= 1 && N < size, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subdomains must be > 0 and < %d, got N = %" PetscInt_FMT, size, N); 11070 *n = 1; 11071 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11072 color = rank / k; 11073 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11074 PetscCall(PetscMalloc1(1, iss)); 11075 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11076 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11077 PetscCallMPI(MPI_Comm_free(&subcomm)); 11078 PetscFunctionReturn(PETSC_SUCCESS); 11079 } 11080 11081 /*@ 11082 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11083 11084 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11085 If they are not the same, uses `MatMatMatMult()`. 11086 11087 Once the coarse grid problem is constructed, correct for interpolation operators 11088 that are not of full rank, which can legitimately happen in the case of non-nested 11089 geometric multigrid. 11090 11091 Input Parameters: 11092 + restrct - restriction operator 11093 . dA - fine grid matrix 11094 . interpolate - interpolation operator 11095 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11096 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11097 11098 Output Parameter: 11099 . A - the Galerkin coarse matrix 11100 11101 Options Database Key: 11102 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11103 11104 Level: developer 11105 11106 Note: 11107 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11108 11109 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11110 @*/ 11111 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11112 { 11113 IS zerorows; 11114 Vec diag; 11115 11116 PetscFunctionBegin; 11117 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11118 /* Construct the coarse grid matrix */ 11119 if (interpolate == restrct) { 11120 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11121 } else { 11122 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11123 } 11124 11125 /* If the interpolation matrix is not of full rank, A will have zero rows. 11126 This can legitimately happen in the case of non-nested geometric multigrid. 11127 In that event, we set the rows of the matrix to the rows of the identity, 11128 ignoring the equations (as the RHS will also be zero). */ 11129 11130 PetscCall(MatFindZeroRows(*A, &zerorows)); 11131 11132 if (zerorows != NULL) { /* if there are any zero rows */ 11133 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11134 PetscCall(MatGetDiagonal(*A, diag)); 11135 PetscCall(VecISSet(diag, zerorows, 1.0)); 11136 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11137 PetscCall(VecDestroy(&diag)); 11138 PetscCall(ISDestroy(&zerorows)); 11139 } 11140 PetscFunctionReturn(PETSC_SUCCESS); 11141 } 11142 11143 /*@C 11144 MatSetOperation - Allows user to set a matrix operation for any matrix type 11145 11146 Logically Collective 11147 11148 Input Parameters: 11149 + mat - the matrix 11150 . op - the name of the operation 11151 - f - the function that provides the operation 11152 11153 Level: developer 11154 11155 Example Usage: 11156 .vb 11157 extern PetscErrorCode usermult(Mat, Vec, Vec); 11158 11159 PetscCall(MatCreateXXX(comm, ..., &A)); 11160 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11161 .ve 11162 11163 Notes: 11164 See the file `include/petscmat.h` for a complete list of matrix 11165 operations, which all have the form MATOP_<OPERATION>, where 11166 <OPERATION> is the name (in all capital letters) of the 11167 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11168 11169 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11170 sequence as the usual matrix interface routines, since they 11171 are intended to be accessed via the usual matrix interface 11172 routines, e.g., 11173 .vb 11174 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11175 .ve 11176 11177 In particular each function MUST return `PETSC_SUCCESS` on success and 11178 nonzero on failure. 11179 11180 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11181 11182 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11183 @*/ 11184 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11185 { 11186 PetscFunctionBegin; 11187 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11188 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11189 (((void (**)(void))mat->ops)[op]) = f; 11190 PetscFunctionReturn(PETSC_SUCCESS); 11191 } 11192 11193 /*@C 11194 MatGetOperation - Gets a matrix operation for any matrix type. 11195 11196 Not Collective 11197 11198 Input Parameters: 11199 + mat - the matrix 11200 - op - the name of the operation 11201 11202 Output Parameter: 11203 . f - the function that provides the operation 11204 11205 Level: developer 11206 11207 Example Usage: 11208 .vb 11209 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11210 11211 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11212 .ve 11213 11214 Notes: 11215 See the file include/petscmat.h for a complete list of matrix 11216 operations, which all have the form MATOP_<OPERATION>, where 11217 <OPERATION> is the name (in all capital letters) of the 11218 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11219 11220 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11221 11222 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11223 @*/ 11224 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11225 { 11226 PetscFunctionBegin; 11227 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11228 *f = (((void (**)(void))mat->ops)[op]); 11229 PetscFunctionReturn(PETSC_SUCCESS); 11230 } 11231 11232 /*@ 11233 MatHasOperation - Determines whether the given matrix supports the particular operation. 11234 11235 Not Collective 11236 11237 Input Parameters: 11238 + mat - the matrix 11239 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11240 11241 Output Parameter: 11242 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11243 11244 Level: advanced 11245 11246 Note: 11247 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11248 11249 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11250 @*/ 11251 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11252 { 11253 PetscFunctionBegin; 11254 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11255 PetscAssertPointer(has, 3); 11256 if (mat->ops->hasoperation) { 11257 PetscUseTypeMethod(mat, hasoperation, op, has); 11258 } else { 11259 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11260 else { 11261 *has = PETSC_FALSE; 11262 if (op == MATOP_CREATE_SUBMATRIX) { 11263 PetscMPIInt size; 11264 11265 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11266 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11267 } 11268 } 11269 } 11270 PetscFunctionReturn(PETSC_SUCCESS); 11271 } 11272 11273 /*@ 11274 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11275 11276 Collective 11277 11278 Input Parameter: 11279 . mat - the matrix 11280 11281 Output Parameter: 11282 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11283 11284 Level: beginner 11285 11286 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11287 @*/ 11288 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11289 { 11290 PetscFunctionBegin; 11291 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11292 PetscValidType(mat, 1); 11293 PetscAssertPointer(cong, 2); 11294 if (!mat->rmap || !mat->cmap) { 11295 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11296 PetscFunctionReturn(PETSC_SUCCESS); 11297 } 11298 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11299 PetscCall(PetscLayoutSetUp(mat->rmap)); 11300 PetscCall(PetscLayoutSetUp(mat->cmap)); 11301 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11302 if (*cong) mat->congruentlayouts = 1; 11303 else mat->congruentlayouts = 0; 11304 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11305 PetscFunctionReturn(PETSC_SUCCESS); 11306 } 11307 11308 PetscErrorCode MatSetInf(Mat A) 11309 { 11310 PetscFunctionBegin; 11311 PetscUseTypeMethod(A, setinf); 11312 PetscFunctionReturn(PETSC_SUCCESS); 11313 } 11314 11315 /*@ 11316 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 11317 and possibly removes small values from the graph structure. 11318 11319 Collective 11320 11321 Input Parameters: 11322 + A - the matrix 11323 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11324 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11325 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11326 . num_idx - size of 'index' array 11327 - index - array of block indices to use for graph strength of connection weight 11328 11329 Output Parameter: 11330 . graph - the resulting graph 11331 11332 Level: advanced 11333 11334 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11335 @*/ 11336 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11337 { 11338 PetscFunctionBegin; 11339 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11340 PetscValidType(A, 1); 11341 PetscValidLogicalCollectiveBool(A, scale, 3); 11342 PetscAssertPointer(graph, 7); 11343 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11344 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11345 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11346 PetscFunctionReturn(PETSC_SUCCESS); 11347 } 11348 11349 /*@ 11350 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11351 meaning the same memory is used for the matrix, and no new memory is allocated. 11352 11353 Collective 11354 11355 Input Parameters: 11356 + A - the matrix 11357 - keep - if for a given row of `A`, the diagonal coefficient is zero, indicates whether it should be left in the structure or eliminated as well 11358 11359 Level: intermediate 11360 11361 Developer Note: 11362 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11363 of the arrays in the data structure are unneeded. 11364 11365 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11366 @*/ 11367 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11368 { 11369 PetscFunctionBegin; 11370 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11371 PetscUseTypeMethod(A, eliminatezeros, keep); 11372 PetscFunctionReturn(PETSC_SUCCESS); 11373 } 11374